Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Motion perception is a complex theme, but some aspects are explained in simple terms in Gestalt psychology under “The Law of Common Fate”. This law stipulates that objects that move together, are perceived as single whole or group, something that is often utilised in GUI design.

Animation Easing

The code below uses a bell curve to generate the animation. The advantage of using this function is that the size of the points return to there original state once the transformation is over. There is however a boundless number of functions that can be used for animation, many of which have been documented by Robert Penner for several programming languages

...

.

...

When used for animation, such functions are often called "easing". Easing can be used to create more natural movements and for creating physics like effects such as bouncing.

Code Block
languagejs

...


let arrayWidth = 20;
let arrayHeight = 20;
let dist_x = 20;
let dist_y = 20;
let shapeWidth = 10;
let shapeHeight = 10;
let duration = 120;
let scaleTimer = 0;
let amplitude = 2; 
let wavelength = 30;
let xOffset;
let yOffset;
var reactorPosition;
 
function setup() {
  createCanvas(800, 700);
  xOffset = floor(width/2-(dist_x*arrayWidth/2));
  yOffset = floor(height/2-(dist_y*arrayHeight/2));
  reactorPosition = createVector(0, 0);
  noStroke();
  fill(0);
}
 
function draw() {
  background(255);
  scaleTimer+=3;
  push();
  translate(xOffset, yOffset);
  for (let i = 0; i<arrayWidth; i++ ) {
    for (let j = 0; j<arrayHeight; j++ ) {
      rectMode(CENTER);
      var myPos =  createVector(i*dist_x, j*dist_y);
      var reactorDistance = dist(reactorPosition.x, reactorPosition.y, myPos.x, myPos.y);
      var myStartTime = int(scaleTimer-reactorDistance);
      var scaler =  bellCurve(myStartTime, shapeWidth, amplitude, wavelength);
      ellipse(myPos.x, myPos.y, scaler, scaler);
    }
  }
  pop();
}
 
function mouse_X() {
  return (mouseX - xOffset); //correct positions matrix translations
}
 
function mouse_Y() {
  return (mouseY - xOffset); //correct positions matrix translations
}

function mouseClicked() {
  scaleTimer = -100;
  reactorPosition.x = mouse_X();
  reactorPosition.y = mouse_Y();
}
 

...

function bellCurve(t, a, b, c) {
// see https://en.wikipedia.org/wiki/Gaussian_function
  // t = time
  // a = start value
  // b = amplitude
  // c = wavelength 
  var scaler = 1+(c/sqrt((c*c)+(t*t)))*b; //bell curve
  return scaler*a;
}
 


Sine function

Code Block
languagejs
var gridWidth = 20;
var gridHeight = 
// alternative equation for easing
function easeInOutQuart (t, b, c, d) {
  // seee http://www.robertpenner.com/easing/
  // t = time
  // b = start value
  // c = change in value
  // d = duration
  if ((t/=d/2) < 1) return c/2*t*t + b;
  return -c/2 * ((--t)*(t-2) - 1) + b;
}20;
var shapeWidth = 20;
var shapeHeight = 20;
var dist_x = 20;
var dist_y = 20;
var duration = 40;
var duration2 = 50;
var scaleTimer = 0;
var amplitude = 2;
var xOffset;
var yOffset;

 
function setup() {
 createCanvas(800, 800);
 xOffset = floor(width/2-(dist_x*gridWidth/2));
 yOffset = floor(height/2-(dist_y*gridHeight/2));
 reactorPosition = createVector(0, 0);

}
 
function draw() {
 background(0);
 //fill(10);
 stroke(0);
 scaleTimer++;
 push(); //saves current position of the coordinate system
 translate(xOffset, yOffset);//translate grid to center
 for (var i = 0; i<gridWidth; i++ ) {
   for (var j = 0; j<gridHeight; j++ ) {
 
   let reactorDistance = dist(reactorPosition.x,   reactorPosition.y, i*dist_x, j*dist_y);
   let myStartTime = int(scaleTimer-reactorDistance);
   let angle = radians(myStartTime)*1.5;
   let _scale = sin(angle)*amplitude;
 
   ellipse(i*dist_x, j*dist_y, shapeWidth*_scale,     shapeHeight*_scale);
   
   }
 }
 pop();
}
 
function mouse_X() {
 return (mouseX - xOffset); //correct positions matrix translations
}
 
function mouse_Y() {
 return (mouseY - xOffset); //correct positions matrix translations
}

function mouseClicked() {
 scaleTimer = 0;
 reactorPosition.x = mouse_X();
 reactorPosition.y = mouse_Y();
}

Exercise

What other wave functions could be used to generate patterns in this way, and how could it be made more responsive? Based on the examples try to integrate another motion to influence the behaviour of the individual shapes.