const canvas = document.querySelector("canvas");
const cHeight = 249;
const cWidth = 72;
canvas.height = cHeight;
canvas.width = cWidth;
const ctx = canvas.getContext("2d");
const bW = 72;
const bH = 48;
const fps = 120;
const duration = 1700;
const frameTime = 1000 / fps;
const elementCount = 6;
const startTime = Date.now();
let previousFrame = startTime;
const timings = {
0: [0.1, 0.1, 0.1, 0.1, 0.1, 1.0, 1.0, 1.0, 1.0, 0.5, 0.1],
1: [0.1, 0.1, 0.1, 0.1, 1.0, 0.9, 0.8, 0.5, 0.5, 0.1, 0.1],
2: [0.1, 0.1, 0.1, 1.0, 0.8, 0.7, 0.6, 0.3, 0.1, 0.1, 0.1],
3: [0.1, 0.1, 1.0, 0.6, 0.4, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
4: [0.1, 1.0, 0.5, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
5: [1.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
};
const timingFunction = (animationTime, animationLength, timing) => {
// How many steps there are in timing definition, we count spaces not steps
const positions = timing.length - 1;
const stepSize = animationLength / positions; // How long time is for each step
// For which step to take values
const animationStep = Math.floor(animationTime / stepSize);
// How much time is elapsed in step
const minMaxTimingDelta = timing[animationStep + 1] - timing[animationStep];
const timingAddition = timing[animationStep];
const timeInStep = animationTime % stepSize;
// Coificient to multiply max value with
const coefficient = timeInStep / stepSize;
const timingCoefficient = coefficient * minMaxTimingDelta;
return timingAddition + timingCoefficient;
};
function drawElement(animationTime) {
ctx.clearRect(0, 0, cWidth, cHeight)
const min = 0;
const max = 1;
const delay = 700;
const inDelay = animationTime < delay;
const newAnimTime = duration - delay;
for (let i = 0; i < elementCount; i++) {
const alpha = inDelay ? 0.1 : timingFunction(
animationTime - delay,
newAnimTime,
timings[i],
min,
max,
)
ctx.globalAlpha = alpha;
ctx.fillStyle = 'green';
ctx.fillRect(0, i * (bH + 3), bW, bH);
}
}
const animate = () => {
if (Date.now() - previousFrame > frameTime) {
previousFrame = Date.now();
drawElement((previousFrame - startTime) % duration);
}
requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
body {
height: 100%;
width: 100%;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
.1 {
opacity: .9;
background-color: blue;
width: 50px;
height: 50px;
border: 1px solid red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<canvas />
</body>
</html>