JSFiddle - React, Tailwind, and code Playground
by intrinsica
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
CSS
body {margin: 0;}
JavaScript
// A web worker is defined inline. It receives mouseXY
// updates, and computes a damped trajectory toward the mouse.
// It posts results at 30fps.
var work = "var data = [100,100,100,100]; \
onmessage = function(e) { \
data[0] = data[0]*0.9 + e.data[0]*0.1; \
data[1] = data[1]*0.9 + e.data[1]*0.1; \
data[2] = data[2]*0.95 + e.data[0]*0.05; \
data[3] = data[3]*0.95 + e.data[1]*0.05; }; \
function draw() {postMessage(data);} \
setInterval(draw, 1000/30); /* draw at 30fps */";
var myWorker, posA = [0,0], posB = [0,0],
awake=0; // <-- serves as a heartbeat
function setup() {
createCanvas(windowWidth, windowHeight);
// define an inline worker and launch it
var blob = new Blob([work]);
myWorker = new Worker(window.URL.createObjectURL(blob));
// handle messages from the worker
myWorker.onmessage = function(e) {
posA = [e.data[0], e.data[1]];
posB = [e.data[2], e.data[3]];
if (awake) backdraw(); // conditional draw
};
frameRate(1); // <-- heart beat: 1fps
}
// when main process is minimized, no drawing necessary
function draw() {
awake++;
setTimeout(function(){awake--;}, 1000); // <-- needs to be >= frame rate
}
// background draw; driven by worker message callback at 30fps
function backdraw() {
background(0,0,0,100);
noFill();
strokeWeight(25);
stroke(0,0,255,64);
ellipse(posB[0], posB[1], 160, 160); // largest ring
stroke(0,0,255,128);
ellipse(posA[0], posA[1], 120, 120); // midsize ring
fill(0,0,255,192);
noStroke();
ellipse(mouseX, mouseY, 100, 100); // primary circle
// send the current mouse coordinates to the web worker
myWorker.postMessage([mouseX,mouseY]);
}