quaintitative

I write about my quantitative explorations in visualisation, data science, machine and deep learning here, as well as other random musings.

For more about me and my other interests, visit playgrd or socials below


Categories
Subscribe

Tweening in p5.js

p5.js is great when it comes to getting a simple animation up and running in the browser, compared to say d3.js, which requires a fair bit more boilerplate.

But one thing that p5.js does not have is an easy way to manage transitions between states, which d3.js has. We could easily create an easing function from scratch to for transitions between states, or to tween between states, but why do so if there are libraries available out there to do it for us.

GSAP’s (or the GreenSock Animation Platform) TweenLite library is great for this. It’s super simple to use. The only tricky thing is to figure out how to make it play nice with the p5.js library’s draw cycle.

Getting it to work with the setup function is quite simple. You simply have to create a original object, insert the object into the TweenLite.to function, and provide the function with the new values of the object that you want it to tween to. All the steps in between will then be computed by the TweenLite function. The code to move an ellipse across the width of the screen will look something like this.

var pos = {x:0, y:0};

function setup(){
    ...
    ellipse(pos.x,pos.y,40,40);
    TweenLite.to(pos, 5, {x:width});
    ...
}

The function TweenLite takes in 3 parameters. The first is the original object (with the starting values), the second is the duration of the tween, and the third is the values at the end state.

To use it within the draw function is a tad more complicated, as you would want the cycle to be repeated as you update the values that you want to start with and end at. But first, let’s start with the setup what we want to do.

var currentPos = [];
var newPos = [];
var colorsPalette;
var numpoints = 80;

function setup() {

    c = createCanvas(600,600);
    c.parent('p5canvas');
    
    colorsPalette = [color(146, 167, 202,25),
            color(186, 196, 219,50),
            color(118, 135, 172,250),
            color(76, 41, 81,250),
            color(144, 62, 92,50),
            color(178, 93, 119,250),
            color(215, 118, 136,250),
            color(246, 156, 164,250),];
    background(colorsPalette[0]);

    frameRate(30);

    for (var i=0;i<numpoints;i++){        
        currentPos.push({
            x: random(width),
            y: random(height),
            c: colorsPalette[6]
        })    
    }
    for (var i=0;i<numpoints;i++){        
        newPos.push({
            x: random(width)+random(),
            y: random(height)+random(),
            c: colorsPalette[6]
        })    
    }

}

What we have done is to create the arrays currentPos and newPos to store the current and new states, some colors, and initialised the currentPos and newPos arrays.

Next, the meat of this post.

function draw() {
    
    background(colorsPalette[0]);

    if (frameCount%300==0){
        for (var i=0;i<numpoints;i++){      
            newPos[i].x = random(width)+random();
            newPos[i].y = random(height)+random();
        }

    }


    for (var i=0;i<numpoints;i++){
        TweenLite.to(currentPos[i], 10, newPos[i]);
        noStroke();
        fill(currentPos[i].c);
        ellipse(currentPos[i].x,currentPos[i].y,3,3);
        noStroke();
        fill(255,150);
        ellipse(currentPos[i].x+2,currentPos[i].y,1,1); 
        ellipse(currentPos[i].x-2,currentPos[i].y,1,1);   
    }

}

What we have done here is to update the newPos object with new x and y positions. Then we iterate through each and every point to apply the tween and draw the ellipses. There are just two things to note -

And that’s it. You can find the full code here. And you can see a demo here, stylised fishes swimming around in a pond.


Articles

AI and UIs
Listing NFTs
Extracting and Processing Wikidata datasets
Extracting and Processing Google Trends data
Extracting and Processing Reddit datasets from PushShift
Extracting and Processing GDELT GKG datasets from BigQuery
Some notes relating to Machine Learning
Some notes relating to Python
Using CCapture.js library with p5.js and three.js
Introduction to PoseNet with three.js
Topic Modelling
Three.js Series - Manipulating vertices in three.js
Three.js Series - Music and three.js
Three.js Series - Simple primer on three.js
HTML Scraping 101
(Almost) The Simplest Server Ever
Tweening in p5.js
Logistic Regression Classification in plain ole Javascript
Introduction to Machine Learning Right Inside the Browser
Nature and Math - Particle Swarm Optimisation
Growing a network garden in D3
Data Analytics with Blender
The Nature of Code Ported to Three.js
Primer on Generative Art in Blender
How normal are you? Checking distributional assumptions.
Monte Carlo Simulation of Value at Risk in Python
Measuring Expected Shortfall in Python
Style Transfer X Generative Art
Measuring Market Risk in Python
Simple charts | crossfilter.js and dc.js
d3.js vs. p5.js for visualisation
Portfolio Optimisation with Tensorflow and D3 Dashboard
Setting Up a Data Lab Environment - Part 6
Setting Up a Data Lab Environment - Part 5
Setting Up a Data Lab Environment - Part 4
Setting Up a Data Lab Environment - Part 3
Setting Up a Data Lab Environment - Part 2
Setting Up a Data Lab Environment - Part 1
Generating a Strange Attractor in three.js
(Almost) All the Most Common Machine Learning Algorithms in Javascript
3 Days of Hand Coding Visualisations - Day 3
3 Days of Hand Coding Visualisations - Day 2
3 Days of Hand Coding Visualisations - Day 1
3 Days of Hand Coding Visualisations - Introduction