summaryrefslogtreecommitdiffstats
path: root/attractors6/demo.js
blob: 96b9717aa8f2a65c1be3b21135af5d3627235031 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
var canvas, ctx;
var canvasW, canvasH;
var particle;
var attractors = [];
var maxDistance;

document.addEventListener( 'DOMContentLoaded', init, false );

function init() {
  canvas = document.querySelector('canvas');
  ctx = canvas.getContext('2d');
  // set size
  canvasW = canvas.width = window.innerWidth - 20;
  canvasH = canvas.height = 240;
  

  canvas.addEventListener( 'mousedown', onMousedown, false );

  particle = new Particle( canvasW / 2, canvasH / 2 );
  var x0 = canvasW * 0.15;
  var x1 = canvasW * 0.5;
  var x2 = canvasW * 0.85;
  attractors.push( new Attractor( x0, canvasH / 2 ) );
  attractors.push( new Attractor( x1, canvasH / 2 ) );
  attractors.push( new Attractor( x2, canvasH / 2 ) );
  maxDistance = Math.abs( x1 - x0 ) * 0.5;

  animate();
}

// -------------------------- animate, render, update -------------------------- //


 ;

function animate() {
  // apply force of attractors to particle
  // reset particle friction
  particle.friction = 0.1;
  if ( !isDragging ) {

    for ( var i=0, len = attractors.length; i < len; i++ ) {
      var attractor = attractors[i];
      var distance = attractor.x - particle.x;
      var sign = distance < 0 ? -1 : 1;
      // normalize
      var force = Math.abs( distance ) < maxDistance ?
        Math.abs( distance ) / maxDistance : 0;
      var friction = force ? 1 - force : 0;
      friction *= 0.3;
      force *= 8;
      force = distance < 0 ? -force : force;
      particle.friction = Math.max( particle.friction, friction );
      particle.applyForce( force );
    }
  }

  particle.update();
  // wrap around
  if ( !isDragging ) {
    particle.x = ( particle.x + canvasW ) % canvasW;
  }
  render();
  rAF( animate );
}

function render() {
  ctx.clearRect( 0, 0, canvasW, canvasH );

  // render particle
  ctx.fillStyle = 'hsla(0, 100%, 50%, 0.5)';
  ctx.beginPath();
  ctx.arc( particle.x, particle.y, 15, 0, Math.PI * 2, true );
  ctx.fill();
  ctx.closePath();

  // render attractor
  ctx.fillStyle = 'hsla(240, 100%, 50%, 0.5)';
  for ( var i=0, len = attractors.length; i < len; i++ ) {
    var attractor = attractors[i];
    ctx.beginPath();
    ctx.arc( attractor.x, attractor.y, 8, 0, Math.PI * 2, true );
    ctx.fill();
    ctx.closePath();
  }
}

// -------------------------- mouse -------------------------- //

var isDragging = false;

function onMousedown( event ) {
  event.preventDefault();
  isDragging = true;
  window.addEventListener( 'mousemove', onMousemove, false );
  window.addEventListener( 'mouseup', onMouseup, false );
  particle.x = event.pageX;
  particle.velocity = 0;
}

var previousX;
var previousTime;
var currentTime;

function onMousemove( event ) {
  // previous
  previousX = particle.x;
  previousTime = currentTime;
  // current
  particle.x = event.pageX;
  currentTime = new Date();
}

function onMouseup( event ) {
  if ( previousX ) {
    particle.velocity = ( particle.x - previousX ) / ( currentTime - previousTime );
    particle.velocity *= 17;
    previousX = null;
  }

  isDragging = false;
  window.removeEventListener( 'mousemove', onMousemove, false );
  window.removeEventListener( 'mousemove', onMouseup, false );
}