JSFiddle - React, Tailwind, and code Playground
by Will Stott
HTML
<canvas id="cvs" width="512", height="160"></canvas>
<br>
<input id="inp" type="range" min="0" max="100" value="50"/>
<button onclick="reset()" text="reset">Reset</button>
<br><br>
<label>Force</label><input id="force" type="number" value="50"/><br>
<label>Fricton</label><input id="friction" type="number"value="11"/><br>
<!--<label>Damping</label><input id="damping" type="number"value="3"/><br>-->
<label>Slew</label><input id="slew" type="number" value="180"/><br>
<label>Max Accel</label><input id="maxacc" type="number" value="400"/><br>
CSS
canvas {
background-color: #ffeeee;
border: 1px solid gray;
}
label {
display: inline-block;
width: 6em;
}
.affecting {
border-right: solid 4px red;
}
JavaScript
let val = 50;
let speed = 0;
const dof = {
force: () => parseFloat(document.getElementById("force").value || 0),
friction: () => parseFloat(document.getElementById("friction").value || 0),
// damping: () => parseFloat(document.getElementById("damping").value || 0),
clampSpeed: (speed) => {
let dom = document.getElementById("slew");
let slew = parseFloat(dom.value || 0);
let speed2 = clamp(speed, -slew, slew);
dom.classList.toggle("affecting", speed2 !== speed);
return speed2;
},
clampAccel: (accel) => {
let dom = document.getElementById("maxacc");
let max = parseFloat(dom.value || 0);
let accel2 = clamp(accel, -max, max);
dom.classList.toggle("affecting", accel2 !== accel);
return accel2;
},
};
function run (demand, timeDelta) {
const error = demand - val;
let acceleration = error * dof.force() - dof.friction() * speed;
acceleration = dof.clampAccel(acceleration);
speed += acceleration * timeDelta;
// speed = clamp(Math.abs(speed) - dof.damping(), 0, 10000000000) * Math.sign(speed);
speed = dof.clampSpeed(speed);
val += speed * timeDelta;
// console.debug(demand, val, speed, acceleration, error);
return val;
}
function clamp(v, min, max) {
if (v < min)
return min;
if (v > max)
return max;
return v;
}
let lastTime = null;
function reset() {
lastTime = null;
val = 50;
speed = 0;
demands.fill(50);
values.fill(50);
slider.value = 50;
}
const dataHeightBorder = 20;
const dataWidth = 400;
const demands = new Array(dataWidth);
const values = new Array(dataWidth);
const canvas = document.getElementById("cvs");
const slider = document.getElementById("inp");
const ctx = canvas.getContext("2d");
function main() {
reset();
function point (ctx, i, val) {
let h = canvas.height - dataHeightBorder * 2;
ctx.lineTo(
i / dataWidth * canvas.width,
(((100 - val) / 100) * h) + dataHeightBorder
);
}
let lastTime = null;
function onTick (t) {
if...