Complex Multiplication
by Josh Pullen
HTML
<img id="grab"...
CSS
canvas {
border: 1px solid black;
width: 100%;
}
img {
display: none;
}
JavaScript
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas.width = 1280;
canvas.height = 720;
const lerp = (a, b, t = 0) => {
if (Array.isArray(a) && Array.isArray(b)) {
let result = [];
for (let i = 0; i < a.length; i++) {
result.push(lerp(a[i], b[i], t));
}
return result;
}
if (t < 0) t = 0;
if (t > 1) t = 1;
return a + (b - a) * t;
}
const sequence = (map, ease = (t) => t) => {
const keyTimes = Object.keys(map).map(n => Number(n)).sort((a, b) => a - b);
return (t) => {
const beforeTime = [...keyTimes].reverse().find(time => time <= t);
const afterTime = keyTimes.find(time => time > t);
if (beforeTime === undefined) return map[afterTime];
if (afterTime === undefined) return map[beforeTime];
return lerp(
map[beforeTime],
map[afterTime],
ease(lerp(0, 1, (t - beforeTime) / (afterTime - beforeTime)))
);
}
}
const ease = {
sin: (t) => (1 - Math.cos(t * Math.PI)) / 2,
out: (t) => 1 - (1 - t) ** 3,
}
function render(t) {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
const progress = sequence({
0: 0,
2.5: 0,
4: 1,
8: 1,
10: 0,
15: 0,
18: 1,
})(t);
const complexMode = lerp(0, 1, 0.5 * (t - 10));
grid(0, complexMode, "#e4e4e4", "#bbb");
grid(progress, complexMode, "#aaa", "#888");
const grabbing = t > 2 && t < 4 || t > 13 && t < 18;
onePoint(progress, complexMode, grabbing);
negTwoPoint(progress, complexMode);
renderMouse(
...sequence({
0: [850, 720],
0.8: [850, 720],
2: [700, 350],
2.5: [700, 350],
4: [840, 350],
5: [840, 350],
6: [900, 500],
12: [900, 500],
13: [685, 335],
15: [685, 335],
18: [825, 195],
18.5: [825, 195],
19.5: [1100, 100]
}, ease.sin)(t),
grabbing
);
}
function getPoint(real, imaginary, progress, complexMode) {
const...