JSDM

HTML

 
1
<canvas id="canvas" ></canvas>

CSS

xxxxxxxxxx
6
 
1
#canvas {
2
  background-color: #000;
3
  position:absolute;
4
  top:0;
5
  left:0;
6
}
? ?
? ?
必须是有效的URL
+ 添加另一个资源

JS

x
 
1
// dependencies: Vector2D
2
function Ball(radius,color,mass,charge,gradient,line, field, sizefield){
3
  if(typeof(radius)==='undefined') radius = 20;
4
  if(typeof(color)==='undefined') color = '#0000ff';
5
  if(typeof(mass)==='undefined') mass = 1;
6
  if(typeof(charge)==='undefined') charge = 0;
7
  if(typeof(gradient)==='undefined') gradient = false;  
8
  if(typeof(line)==='undefined') line = false;
9
  if(typeof(field)==='undefined') field = false;
10
  if(typeof(sizefield)==='undefined') sizefield = 0;  
11
  this.radius = radius;
12
  this.color = color;
13
  this.mass = mass;
14
  this.charge = charge;
15
  this.gradient = gradient;
16
  this.line = line;
17
  this.x = 0;
18
  this.y = 0;
19
  this.vx = 0;
20
  this.vy = 0;  
21
  this.angVelo = 0;
22
  this.field = field;
23
  this.sizefield = sizefield;
24
}   
25
26
Ball.prototype = {
27
  get pos2D (){
28
    return new Vector2D(this.x,this.y);     
29
  },
30
  set pos2D (pos){
31
    this.x = pos.x;
32
    this.y = pos.y;
33
  },
34
  get velo2D (){
35
    return new Vector2D(this.vx,this.vy);     
36
  },
37
  set velo2D (velo){
38
    this.vx = velo.x;
39
    this.vy = velo.y;
40
  },
41
  draw: function (context) {
42
    if(this.field){
43
      context.fillStyle = "rgba(32,214,199,.3)";
44
      context.beginPath();
45
      context.arc(this.x, this.y, this.radius + this.sizefield , 0, 2*Math.PI, true);
46
      context.closePath();2
47
      context.fill();
48
    }
49
    if (this.gradient){
50
      grad = context.createRadialGradient(this.x,this.y,0,this.x,this.y,this.radius);
51
      grad.addColorStop(0,'#ffffff');
52
      grad.addColorStop(1,this.color);
53
      context.fillStyle = grad;
54
    }else{
55
      context.fillStyle = this.color;
56
    } 
57
    context.beginPath();
58
    context.arc(this.x, this.y, this.radius, 0, 2*Math.PI, true);
59
    context.closePath();
60
    context.fill();   
61
    if (this.line){
62
      context.strokeStyle = this.color;
63
      context.lineWidth = 1;
64
      context.beginPath();
65
      context.moveTo(this.x-this.radius,this.y);
66
      context.lineTo(this.x+this.radius,this.y);
67
      context.moveTo(this.x,this.y+this.radius);      
68
      context.lineTo(this.x,this.y-this.radius);
69
      context.closePath();
70
      context.stroke();
71
    }
72
    
73
  }
74
};
75
76
function Forces(){
77
}
78
79
// STATIC METHODS
80
Forces.zeroForce = function() {
81
  return (new Vector2D(0,0));
82
}
83
Forces.constantGravity = function(m,g){
84
  return new Vector2D(0,m*g);
85
}
86
Forces.gravity = function(G,m1,m2,r){
87
  return r.multiply(-G*m1*m2/(r.lengthSquared()*r.length()));
88
}
89
Forces.electric = function(k,q1,q2,r){
90
  return r.multiply(k*q1*q2/(r.lengthSquared()*r.length()));
91
}
92
Forces.forceField = function(q,E) {
93
  return E.multiply(q);
94
}
95
Forces.lorentz = function(q,E,B,vel) {
96
  return E.multiply(q).add(vel.perp(q*B*vel.length()));
97
}   
98
Forces.central = function(k,n,r) {
99
  return r.multiply(k*Math.pow(r.length(),n-1));
100
}
101
Forces.linearDrag = function(k,vel){
102
  var force;
103
  var velMag = vel.length();
104
  if (velMag > 0) {
105
    force = vel.multiply(-k);
106
  }else {
107
    force = new Vector2D(0,0);
108
  }
109
  return force;
110
}
111
Forces.drag = function(k,vel) {
112
  var force;
113
  var velMag = vel.length();
114
  if (velMag > 0) {
115
    force = vel.multiply(-k*velMag);
116
  }
117
  else {
118
    force = new Vector2D(0,0);
119
  }
120
  return force;     
121
}
122
Forces.lift = function(k,vel) {
123
  var force;
124
  var velMag = vel.length();
125
  if (velMag > 0) {
126
    force = vel.perp(k*velMag);
127
  }
128
  else {
129
    force = new Vector2D(0,0);
130
  }
131
  return force;     
132
}     
133
Forces.upthrust = function(rho,V,g) {
134
  return new Vector2D(0,-rho*V*g);
135
} 
136
Forces.vortex = function(k,r0,r){
137
  var force;
138
  var rMag = r.length();
139
  if (rMag > 0){
140
    if (rMag > r0) {
141
      force = r.multiply(-k*Math.pow(r0/rMag,4));
142
    }else{
143
      force = r.multiply(k);
144
    }
145
  }else{
146
    force = new Vector2D(0,0);
147
  }
148
  return force;
149
} 
150
Forces.spring = function(k,r){
151
  return r.multiply(-k);
152
}   
153
Forces.damping = function(c,vel){
154
  var force;
155
  var velMag = vel.length();
156
  if (velMag>0) {
157
    force = vel.multiply(-c);
158
  }
159
  else {
160
    force = new Vector2D(0,0);
161
  }
162
  return force;
163
}   
164
Forces.add = function(arr){
165
    var forceSum = new Vector2D(0,0);
166
    for (var i=0; i<arr.length; i++){
167
    var force = arr[i];
168
    forceSum.incrementBy(force);
169
  }
170
  return forceSum;
171
}
172
173
function Vector2D(x,y) {
174
  this.x = x;
175
  this.y = y;   
176
}   
177
178
// PUBLIC METHODS 
179
Vector2D.prototype = {    
180
  lengthSquared: function(){
181
    return this.x*this.x + this.y*this.y;
182
  },
183
  length: function(){
184
    return Math.sqrt(this.lengthSquared());
185
  },  
186
  angle: function(){
187
    return Math.atan2(this.y,this.x);
188
  },  
189
  clone: function() {
190
    return new Vector2D(this.x,this.y);
191
  },
192
  negate: function() {
193
    this.x = - this.x;
194
    this.y = - this.y;
195
  },
196
  unit: function() {
197
    var length = this.length(); 
198
    if (length > 0) {
199
      return new Vector2D(this.x/length,this.y/length);
200
    }else{
201
      return new Vector2D(0,0);
202
    }
203
  },    
204
  normalize: function() {
205
    var length = this.length();
206
    if (length > 0) {
207
      this.x /= length;
208
      this.y /= length;
209
    }
210
    return this.length();
211
  },
212
  add: function(vec) {
213
    return new Vector2D(this.x + vec.x,this.y + vec.y);
214
  },
215
  incrementBy: function(vec) {
216
    this.x += vec.x;
217
    this.y += vec.y;
218
  },    
219
  subtract: function(vec) {
220
    return new Vector2D(this.x - vec.x,this.y - vec.y);
221
  },
222
  decrementBy: function(vec) {
223
    this.x -= vec.x;
224
    this.y -= vec.y;
225
  },    
226
  multiply: function(k) {
227
    return new Vector2D(k*this.x,k*this.y);
228
  },    
229
  addScaled: function(vec,k) {
230
    return new Vector2D(this.x + k*vec.x, this.y + k*vec.y);
231
  },  
232
  scaleBy: function(k) {
233
    this.x *= k;
234
    this.y *= k;
235
  },
236
  dotProduct: function(vec) {
237
    return this.x*vec.x + this.y*vec.y;
238
  },
239
  projection: function(vec) {
240
    var length = this.length();
241
    var lengthVec = vec.length();
242
    var proj;
243
    if( (length == 0) || ( lengthVec == 0) ){
244
      proj = 0;
245
    }else {
246
      proj = (this.x*vec.x + this.y*vec.y)/lengthVec;
247
    }
248
    return proj;
249
  },
250
  project: function(vec) {
251
    return vec.para(this.projection(vec));
252
  },    
253
  para: function(u,positive){
254
    if (typeof(positive)==='undefined') positive = true;
255
    var length = this.length();
256
    var vec = new Vector2D(this.x, this.y);
257
    if (positive){
258
      vec.scaleBy(u/length);
259
    }else{
260
      vec.scaleBy(-u/length);       
261
    }
262
    return vec;
263
  },
264
  perp: function(u,anticlockwise){
265
    if (typeof(anticlockwise)==='undefined') anticlockwise = true;
266
    var length = this.length();
267
    var vec = new Vector2D(this.y, -this.x);
268
    if (length > 0) {
269
      if (anticlockwise){ // anticlockwise with respect to canvas coordinate system
270
        vec.scaleBy(u/length);
271
      }else{
272
        vec.scaleBy(-u/length);       
273
      }
274
    }else{
275
      vec = new Vector2D(0,0);
276
    } 
277
    return vec;
278
  } 
279
};    
280
281
// STATIC METHODS
282
Vector2D.distance =  function(vec1,vec2){
283
  return (vec1.subtract(vec2)).length(); 
284
}
285
Vector2D.angleBetween = function(vec1,vec2){
286
  return Math.acos(vec1.dotProduct(vec2)/(vec1.length()*vec2.length()));
287
}
288
Vector2D.scale = function(vec,sca){
289
  vec.x *= sca;
290
  vec.y *= sca;
291
}
292
Vector2D.vector2D = function(mag,angle,clockwise){
293
  if (typeof(clockwise)==='undefined') clockwise = true;
294
  var vec = new Vector2D(0,0);
295
  vec.x = mag*Math.cos(angle);
296
  vec.y = mag*Math.sin(angle);
297
  if (!clockwise){
298
    vec.y *= -1;
299
  }
300
  return vec;
301
}
302
303
var canvas = document.getElementById('canvas');
304
var context = canvas.getContext('2d'); 
305
306
// size
307
var W = window.innerWidth,
308
    H = window.innerHeight,
309
    halfW = W / 2,
310
    halfH = H / 2;
311
312
canvas.width =  W;
313
canvas.height =  H;
314
315
var G = 1;
316
var c = 200;
317
var attractors;
318
var orbiters;
319
var t0;
320
var dt;
321
var force;
322
var acc;
323
var numOrbiters = 50;
324
var rows = 10;
325
var cols = 10;
326
var refPoint = new Vector2D( W / cols / 2, W / rows / 2);
327
var spacing = W / cols ;
328
var numAttractors = rows * cols;
329
330
window.onload = init; 
331
332
function init() {
333
  // create attractors
334
  attractors = new Array();
335
  for (var i=0; i<cols*rows; i++){
336
    var color = "rgba(17,63,89,1)";
337
    var r = 10;
338
    var m = (0.5*c*c/G)*r;
339
    var attractor = new Ball(r,color,m,0,true, false, true, 30);  
340
    var ncol = Math.floor(i/rows);
341
    attractor.pos2D = new Vector2D(refPoint.x+ncol*spacing,refPoint.y+(i-ncol*rows-1)*spacing);
342
    attractor.draw(context);
343
    attractors.push(attractor);
344
  } 
345
346
  // create orbiters
347
  orbiters = new Array(); 
348
  for (var i=0; i<numOrbiters; i++){
349
    var color = 'rgba(243,237,91,1)'; 
350
    var orbiter = new Ball(3,color,1,0,false,false,true, 5);  
351
    orbiter.pos2D = new Vector2D(Math.random()*canvas.width,Math.random()*canvas.height);
352
    orbiter.velo2D = new Vector2D((Math.random()-0.5)*100,(Math.random()-0.5)*100);
353
    orbiter.draw(context);
354
    orbiters.push(orbiter);
355
  }  
356
  t0 = new Date().getTime(); 
357
358
  window.addEventListener( 'mousedown', onDocumentMouseDown, false );
359
  window.addEventListener( 'resize', onResize, false );
360
  animFrame();
361
}
362
363
function onResize( e ){
364
    W = window.innerWidth;
365
    H = window.innerHeight;
366
    halfW = W / 2;
367
    halfH = H / 2;
368
369
    canvas.width =  W;
370
    canvas.height =  H;
371
    spacing = W / cols ;
372
}
373
374
function onDocumentMouseDown( e ){
375
  if (e.pageX || e.pageY) {
376
    posx = e.pageX;
377
    posy = e.pageY;
378
  }
379
  else if (e.clientX || e.clientY)    {
380
    posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
381
    posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
382
  }
383
384
  var color = 'rgba(243,237,91,1)'; 
385
  var orbiter = new Ball(3,color,1,0,false,false,true, 5);  
386
  orbiter.pos2D = new Vector2D(posx,posy);
387
  orbiter.velo2D = new Vector2D((Math.random()-0.5)*100,(Math.random()-0.5)*100);
388
  orbiter.draw(context);
389
  orbiters.push(orbiter);
390
  numOrbiters++;
391
  console.log(numOrbiters);
392
393
}
394
395
function animFrame(){
396
  requestAnimationFrame(animFrame,canvas);
397
  onTimer(); 
398
}
399
function onTimer(){
400
  var t1 = new Date().getTime(); 
401
  dt = 0.001*(t1-t0); 
402
  t0 = t1;
403
  if (dt>0.2) {dt=0;};  
404
  move();
405
}
406
function move(){
407
  
408
  context.clearRect(0, 0, canvas.width, canvas.height);
409
  
410
  for (var i=0; i<numOrbiters; i++){
411
    var orbiter = orbiters[i];  
412
    moveObject(orbiter);
413
    calcForce(orbiter);
414
    updateAccel(orbiter.mass);
415
    updateVelo(orbiter);        
416
  }
417
  for (var i=0; i<numAttractors; i++){
418
    var attractor = attractors[i];
419
    attractor.draw(context);        
420
  }
421
422
423
}
424
425
function moveObject(obj){
426
  obj.pos2D = obj.pos2D.addScaled(obj.velo2D,dt); 
427
  if (obj.x < 0 || obj.x > canvas.width || obj.y < 0 || obj.y > canvas.height){
428
    recycleOrbiter(obj);
429
  }
430
  obj.draw(context);  
431
}
432
function updateAccel(mass){
433
  acc = force.multiply(1/mass);
434
} 
435
function updateVelo(obj){
436
  obj.velo2D = obj.velo2D.addScaled(acc,dt);        
437
}
438
function calcForce(obj){  
439
  var gravity;
440
  force = Forces.zeroForce();
441
  for (var i=0; i<numAttractors; i++){
442
    var attractor = attractors[i];  
443
    var dist = obj.pos2D.subtract(attractor.pos2D);
444
    if (dist.length() < attractor.radius+obj.radius+attractor.sizefield){
445
      context.strokeStyle = obj.color;
446
      context.lineWidth = .5;
447
      context.beginPath();
448
      context.moveTo(obj.pos2D.x,obj.pos2D.y);
449
      context.lineTo(attractor.pos2D.x,attractor.pos2D.y);
450
      context.closePath();
451
      context.stroke();
452
    }
453
    if (dist.length() > attractor.radius+obj.radius){
454
      gravity = Forces.gravity(G,attractor.mass,obj.mass,dist);
455
      force = Forces.add([force, gravity]); 
456
    }else{
457
      // normal velocity vectors just before the impact
458
      var normalVelo1 = obj.velo2D.project(dist);
459
      var normalVelo2 = attractor.velo2D.project(dist);     
460
      // tangential velocity vectors
461
      var tangentVelo1 = obj.velo2D.subtract(normalVelo1);
462
      var tangentVelo2 = attractor.velo2D.subtract(normalVelo2);
463
      // move particles so that they just touch 
464
      var L = obj.radius + attractor.radius-dist.length();
465
      var vrel = normalVelo1.subtract(normalVelo2).length();
466
      obj.pos2D = obj.pos2D.addScaled(normalVelo1,-L/vrel);
467
      attractor.pos2D = attractor.pos2D.addScaled(normalVelo2,-L/vrel);       
468
      // normal velocity components after the impact
469
      var m1 = obj.mass;
470
      var m2 = attractor.mass;
471
      var u1 = normalVelo1.projection(dist);
472
      var u2 = normalVelo2.projection(dist);      
473
      var v1 = ((m1-m2)*u1+2*m2*u2)/(m1+m2);
474
      var v2 = ((m2-m1)*u2+2*m1*u1)/(m1+m2);
475
      // normal velocity vectors after collision
476
      normalVelo1 = dist.para(v1);
477
      normalVelo2 = dist.para(v2);
478
      // final velocity vectors after collision
479
      obj.velo2D = normalVelo1.add(tangentVelo1);
480
    }
481
  }     
482
}
483
function recycleOrbiter(obj){
484
  obj.pos2D = new Vector2D(Math.random()*canvas.width,Math.random()*canvas.height);
485
  obj.velo2D = new Vector2D((Math.random()-0.5)*100,(Math.random()-0.5)*100);
486
}
487
488
489
490
491
必须是有效的URL
+ 添加另一个资源
Close

文件管理 点击文件查看URL

图片

  1. 暂无文件

CSS

  1. 暂无文件

JavaScript

  1. 暂无文件

其他

  1. 暂无文件
拖动文件到上面的区域或者:
加载中 ..................