То, с чем вы имеете дело, - это основы работы анимации.
Чтобы анимация работала, вам нужно, как неупорядоченный список,
- сцена , с некоторыми элементами, которые зритель должен иметь возможность идентифицировать какперсонажи, или, в вашем случае, сплошной цвет.
- средство визуализации , которое хорошо отразит вашу сцену в некоторой графической форме.Это может быть рисунок рукой на углу ноутбука в случае низкорамной флип-книги или функция рисования в случае компьютерной графики.
- движок , что-то такое, чтообновит положение наших движущихся элементов в сцене и представит следующую визуализированную графику, отмеченную галочкой через определенный промежуток времени.Проведите пальцем по флипбуку, некоторые методы, основанные на времени, в компьютерной графике.
setInterval
- это один из таких методов, но лучше начать прямо с правильного инструмента, поэтому позвольте мне представить вам requestAnimationFrame , который является лучшим способом задействовать графическую анимацию в браузере.В основном, это запланирует функцию обратного вызова до следующего обновления экрана, позволяя всегда синхронизировать анимацию с наилучшей экономией энергии.
Итак, давайте создадим ее;)
Элементами нашей сцены в вашем случае могут быть только три компонента сплошного цвета, который мы будем анимировать:
const color = [255, 255, 255]; // [red, green, blue]
Средство визуализации возьмет его анимацию.Поскольку в вашей настройке есть несколько ключевых кадров , необходимо вычислить между кадрами.Здесь я просто покажу базовый движок приращения кадров, но было бы лучше использовать основанный на времени, но я подумал, что сейчас это может быть слишком много ...
Так что мы будем держать переменную позицииздесь, после вызова currentFrame
, чтобы мы могли знать, где мы находимся в анимации, от какого ключевого кадра к какому другому мы идем, и вычислить правильные значения для нашего промежуточного кадра.На каждой итерации (каждом кадре) мы будем увеличивать эту переменную до тех пор, пока не достигнем общего количества кадров, из которых будет создана наша анимация.На этом этапе мы сможем запустить его снова, используя оператор по модулю %
.
const color = [255, 255, 255]; // [red, green, blue]
const keyFrames = [
[255, 255, 255], // white
[255, 0, 0], // to red
[0, 255, 0], // to green
[0, 0, 255] // to blue
];
const duration = 5; // in seconds
const totalFrames = 60 * duration; // 60 FPS
let currentFrame = 0;
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
function update() {
// update currentFrame, relative to the whole animation duration
currentFrame = (currentFrame + 1) % totalFrames;
// make it relative to our key-frames
const keyFrameIndex = currentFrame / (totalFrames / keyFrames.length);
// Now we know our previous and next key-frames
const prev = keyFrames[Math.floor(keyFrameIndex) % keyFrames.length];
const next = keyFrames[Math.ceil(keyFrameIndex) % keyFrames.length];
// We need to get the in-between ratio (that's the decimal of our floating index)
const inBetweenRatio = keyFrameIndex - Math.floor(keyFrameIndex);
//now we can update our color
calculateInBetween(color, prev, next, inBetweenRatio);
}
function calculateInBetween(color, prev, next, ratio) {
// simply update each channel of our current color
color[0] = Math.floor((next[0] - prev[0]) * ratio) + prev[0];
color[1] = Math.floor((next[1] - prev[1]) * ratio) + prev[1];
color[2] = Math.floor((next[2] - prev[2]) * ratio) + prev[2];
}
function draw() {
// clear all
ctx.clearRect(0, 0, canvas.width, canvas.height);
// render
ctx.fillStyle = "rgb(" + color + ")";
ctx.fillRect(0, 0, 200, 200);
}
// our animation loop
function anim() {
// update the scene
update();
// then render it
draw();
// start again at next screen refresh
requestAnimationFrame(anim);
}
// let's begin
anim();
<canvas id="canvas" width="200" height="200"></canvas>