我正在尝试在画布中制作动画,其中只有一个从白色到红色再到绿色再到蓝色再到白色的实心矩形。我认为颜色可以正常工作,但是它发生得太快,甚至看不到任何东西,因此我搜索了一个等待或延迟选项,并遇到了setInterval方法。我尽了一切努力使它正常运行,但是没有运气:
这是我编写的简洁代码。
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style type="text/css">
canvas { border: 3px solid black; }
</style>
</head>
<body>
<div>
<button onclick="draw()">Start the gradient</button><br><br>
<canvas id="can" width="200" heigth="200"></canvas>
</div>
</body>
</html>
Javascript:
function draw() {
var can = document.getElementById('can');
if (can.getContext) {
var ctx = can.getContext('2d');
var r = 0;
var g = 0;
var b = 0;
var i;
for(i=0;i<255;i++){
ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
ctx.fillRect(0, 0, 200, 200);
r = r + 1;
}
for(i=0;i<255;i++){
ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
ctx.fillRect(0, 0, 200, 200);
r = r - 1;
g = g + 1;
}
for(i=0;i<255;i++){
ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
ctx.fillRect(0, 0, 200, 200);
g = g - 1;
b = b + 1;
}
for(i=0;i<255;i++){
ctx.fillStyle = 'rgb('+r+', '+g+', '+b+')';
ctx.fillRect(0, 0, 200, 200);
r = r + 1;
g = g + 1;
}
}
//'can' is the canvas//
//Red->Green->Blue//
}
答案 0 :(得分:1)
这是一种快速而肮脏的方法。您在开始时设置了一堆超时:
function draw() {
var can = document.getElementById('can');
if (can.getContext) {
var ctx = can.getContext('2d');
var r = 0;
var g = 0;
var b = 0;
var i;
var numColors = 255;
var delay = 0; // ms
var delta = 5; // ms
for (i = 0; i < numColors; i++) {
delay += delta;
setTimeout(function () {
ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
ctx.fillRect(0, 0, 200, 200);
r = r + 1;
}, delay);
}
for (i = 0; i < numColors; i++) {
delay += delta;
setTimeout(function () {
ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
ctx.fillRect(0, 0, 200, 200);
r = r - 1;
g = g + 1;
}, delay);
}
for (i = 0; i < numColors; i++) {
delay += delta;
setTimeout(function () {
ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
ctx.fillRect(0, 0, 200, 200);
g = g - 1;
b = b + 1;
}, delay);
}
for (i = 0; i < numColors; i++) {
delay += delta;
setTimeout(function () {
ctx.fillStyle = 'rgb(' + r + ', ' + g + ', ' + b + ')';
ctx.fillRect(0, 0, 200, 200);
r = r + 1;
g = g + 1;
}, delay);
}
}
}
答案 1 :(得分:1)
您要处理的是动画工作原理的基础。
要使动画正常工作,您需要作为无序列表,
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>