JSFiddle - React, Tailwind, and code Playground

by jcubed111

HTML

<div id="wrapper">
	<canvas id="main" width=800 height=400></canvas>
	<canvas id="timePos" width=800 height=400></canvas>
</div>
<canvas id="animation" width=400 height=300></canvas>

CSS

canvas{
	background: #fff;
}

#timePos{
	background: transparent;
}

#wrapper{
	position: relative;
	width: 800px;
	height: 400px;
	margin-bottom: 10px;
}

#main, #timePos{
	position: absolute;
	top: 0;
	left: 0;
}

JavaScript

var forcePoints = [0, .1, .2, .2, .4, .4, .2, .1, -.2, -.2, -.1, 0, .2, .2, .2, .1, -.1, -.2,
-.3, 0, .1, 0, -.1, .1, .1, .1, .2, .4, .5, .5, .5, .5, .5, .2, .2, .2, .2, 0, -.1];

function buildForcePoints(endPadding) {
	while(forcePoints.length < (60-endPadding)/0.2) {
		let minForce = -0.4;
		let maxForce = 1.0;
		let variance = 0.4;

		let upper, lower;
		let prev = forcePoints[forcePoints.length-1];
		if(prev + variance > maxForce) {
			upper = maxForce;
			lower = maxForce - variance*2;
		}else if(prev - variance < minForce) {
			upper = minForce + variance*2;
			lower = minForce;
		}else{
			upper = prev + variance;
			lower = prev - variance;
		}

		let next = Math.random()*variance*2 + lower;
		let num = Math.ceil(Math.random()*5);
		for(let i=0; i<num; i++) {
			forcePoints.push(next);
		}
	}
}

/*for(let tStep=1; tStep < 60; tStep++) {
	forcePoints[tStep] = forcePoints[tStep-1] + (Math.random() - 0.5)*0.05;
	forcePoints[tStep] = tStep % 2;
	if(tStep > 5) forcePoints[tStep] = 0;
}*/
	
function f(t) {
	let period = 0.2;
	t = t/period;
	let i = Math.floor(t);
	let n = i+1;
	let s = (t % 1);
	
	let start = forcePoints[i] || 0;
	let diff = (forcePoints[n] - start) || 0;
	return start + diff * s;
}

var minT = 0;
var maxT = 60;
var stepSize = 0.01;

var period = 1.2; // period in seconds
var zeta = 0.35; // damping ratio. zeta < 1 is underdamped

/*
period = 2.2;
zeta = 0.05;
/**/

zeta = 1;
period = 1.2;

var positions = [0];
var velocities = [0];

var frequency = 1.0 / period;
var w1 = 2*Math.PI * frequency; // real angular frequency
var w0 = zeta < 1 ? (w1 / Math.sqrt(1 - zeta*zeta)) : w1;

var lambda = w0*zeta; // exponential decay rate
var timeTo0 = (zeta <= 1) ? (Math.log(0.005)/-lambda + 0.1) : (zeta*1.5/frequency);
timeTo0 = Math.max(2, Math.min(timeTo0, 10));

buildForcePoints(0 && timeTo0);

var k = w0 * w0;
var c = zeta * 2 * w0;
// note: m is 1

var steps = Math.ceil((maxT - minT) / stepSize);

function tStepToT(tStep) {
	return tStep * stepSize +...