0

I am looking for a "random-dot kinematograms" implementation in javascript/HTML (preferably in ReactJS) that I can use in web-based experiments.

enter image description here enter image description here

Basically, dots moving (arrows indicate motion direction) within a visual field (the circle canvas). Signal dots (shown as filled circles) all move in the same direction, while the noise dots can move in random directions. In the actual display, the correlated and uncorrelated dots in a frame appear the same; the filled and open dots are used in the figure only to explain the principle.

Where can I find an implementation for something like this, where the user can specify the direction using a mouse or slider? Or how would one approach implementing this task in ReactJS? (new to javascript, so tips would be highly appreciated).

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
amaatouq
  • 2,297
  • 5
  • 29
  • 50

1 Answers1

2

I've build you simple canvas based kinematogram that you should extend to your needs. What I've done so far is:

  • added bucket of balls (total:100) = 50 black, 50 white
  • blacks are going in strait direction
  • whites are going randomly and they also bounce from walls
  • whites are going in random speed
  • blacks are going in constant speed

To adapt blacks directions you could start by looking in this answer to determine the mouse direction and patch my balls.push loop for that.

To be able to vary balls ratio, I'd add input field somewhere on page and replace my hardcoded noise variable.. something like:

<input type="text" id="t" />

and in javascript pick it like:

var t = document.getElementById("t");
t.addEventListener('keyup', function(ev){ /* update value */ }, false);

hope this helps you in your research and I do encourage you to take a look into the code that I'm posting so try to learn it and extend it :)

;(function() {
  
  'use strict'; 
  var c = document.getElementById('c');
  var t = document.getElementById('t');
  var ctx = c.getContext('2d');
  var w = c.width = window.innerWidth;
  var h = c.height = window.innerHeight;
  // current dots
  var balls=[];
  var total = 100;
  var noise = 50; // here we could pick the value from user input
  var bounce = -1;
  for(var i=0 ; i<total ; i++){
    balls.push({
      x : Math.random() * w,
      y : Math.random() * h,
      vx : ( i < noise ) ? (Math.random() * (2.5 - 1 + 1) + 1) : 2,
      vy : ( i < noise ) ? (Math.random() * (2.5 - 1 + 1) + 1) : 2,
    }) 
  }

  // draw all balls each frame
  function draw() {
    ctx.clearRect(0, 0, w, h);
    var j, dot;
    for(j = 0; j < total; j++) {
        dot = balls[j];
        ctx.beginPath();
        ctx.arc(dot.x, dot.y, 4, 0, Math.PI * 2, false);
        ctx.fillStyle = (j > noise) ? "rgb(0,0,0)" : "#fff";
        ctx.fill(); 
        ctx.strokeStyle = 'black';
        (j < noise) ? ctx.stroke() : '';
    }
  }

  // movement function
  function update(){
    var i,dot;
    for( i=0 ; i< total ; i++){
      dot = balls[i];
      dot.x += dot.vx;
      dot.y += dot.vy;
      // if ball is white, bounce it
      if( i < noise){
        if(dot.x > w){
          dot.x =  w;
          dot.vx *= bounce;
        }else if(dot.x <0){
          dot.x = 0;
          dot.vx *= bounce;
        }
        if(dot.y > h){
          dot.y = h;
          dot.vy *= bounce;
        }else if(dot.y<0){
          dot.y = 0;
          dot.vy *= bounce;
        }
      // if ball is black do not bounce
      } else {
        if(dot.x > w){
          dot.x =  0;
        }else if(dot.x <0){
          dot.x = w;
        }
        if(dot.y > h){
          dot.y = 0;
        }else if(dot.y<0){
          dot.y = h;
        }        
      }
    }
  }

  // loop the animation
  requestAnimationFrame(function loop() {
    requestAnimationFrame(loop);
      update();
      draw();
  }); 
})();
html,
body {
  padding: 0;
  margin: 0;
}

canvas {
  display: block;
  background: white;
}
<canvas id="c"></canvas>
Kresimir Pendic
  • 3,597
  • 1
  • 21
  • 28