以不同的速率在 canvas 上绘制图像
Draw images on canvas at different rates
给定两个不同的图像(例如 image A
和 image B
),假设我想以大约 60 FPS 的速率在 canvas 上绘制 image A
并且我想以大约 30 FPS 的速度绘制 image B
。
我的问题是,使用 requestAnimationFrame 最好的方法是什么?我应该创建 2 个 canvases 吗?
requestAnimationFrame
的回调接收一个时间戳作为它的第一个参数。使用该时间戳计算回调的最后一次执行和当前执行之间经过的时间并根据该时间绘制。
下面是一个演示上述原理的简单示例:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let last100 = 0;
let last500 = 0;
function frame(time) {
ctx.fillStyle = 'rgb(' + Math.random() * 255 + ', 0, 0)';
// 10 frames per second (1000/10 = 100):
if (time > last100 + 100) {
ctx.fillRect(0, 0, 100, 100);
last100 = time;
}
// 2 frames per second (1000/2 = 500):
if (time > last500 + 500) {
ctx.fillRect(200, 0, 100, 100);
last500 = time;
}
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
<canvas id="canvas"></canvas>
您也可以使用 2 个画布,但让它们充当图层,即 "stack them" 使用绝对定位。
有a helpful article here, written by James Litten
我开始了fiddle;它需要进行一些调整以满足您的需求(代码与代码段相同)
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
var ctx1 = layer1.getContext("2d");
var ctx2 = layer2.getContext("2d");
var img1 = loadImage('http://www.rachelgallen.com/images/purpleflowers.jpg', main);
var img2 = loadImage('http://www.rachelgallen.com/images/yellowflowers.jpg', main);
var imagesLoaded = 0;
function main() {
imagesLoaded += 1;
if (imagesLoaded == 2) {
// set alpha for individual images as desired
ctx1.globalAlpha = 0.8;
ctx2.globalAlpha = 0.5;
drawAll();
}
}
function draw1() {
frameRate = 30;
ctx1.clearRect(0, 0, 250, 150);
ctx1.beginPath();
ctx1.rect(0, 0, 250, 150);
ctx1.drawImage(img1, 0, 0); //draw 1st image
ctx1.closePath();
}
function draw2() {
frameRate = 60;
ctx2.clearRect(0, 0, 250, 150);
ctx2.beginPath();
ctx2.rect(0, 0, 250, 150);
ctx2.drawImage(img2, 0, 0); //draw 2nd image
ctx2.closePath();
}
function drawAll() {
draw1();
draw2();
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
#layer1,
#layer2 {
position: absolute;
top: 0;
left: 0;
}
<canvas id="layer1">
</canvas>
<canvas id="layer2">
</canvas>
给定两个不同的图像(例如 image A
和 image B
),假设我想以大约 60 FPS 的速率在 canvas 上绘制 image A
并且我想以大约 30 FPS 的速度绘制 image B
。
我的问题是,使用 requestAnimationFrame 最好的方法是什么?我应该创建 2 个 canvases 吗?
requestAnimationFrame
的回调接收一个时间戳作为它的第一个参数。使用该时间戳计算回调的最后一次执行和当前执行之间经过的时间并根据该时间绘制。
下面是一个演示上述原理的简单示例:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let last100 = 0;
let last500 = 0;
function frame(time) {
ctx.fillStyle = 'rgb(' + Math.random() * 255 + ', 0, 0)';
// 10 frames per second (1000/10 = 100):
if (time > last100 + 100) {
ctx.fillRect(0, 0, 100, 100);
last100 = time;
}
// 2 frames per second (1000/2 = 500):
if (time > last500 + 500) {
ctx.fillRect(200, 0, 100, 100);
last500 = time;
}
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
<canvas id="canvas"></canvas>
您也可以使用 2 个画布,但让它们充当图层,即 "stack them" 使用绝对定位。
有a helpful article here, written by James Litten
我开始了fiddle;它需要进行一些调整以满足您的需求(代码与代码段相同)
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
var ctx1 = layer1.getContext("2d");
var ctx2 = layer2.getContext("2d");
var img1 = loadImage('http://www.rachelgallen.com/images/purpleflowers.jpg', main);
var img2 = loadImage('http://www.rachelgallen.com/images/yellowflowers.jpg', main);
var imagesLoaded = 0;
function main() {
imagesLoaded += 1;
if (imagesLoaded == 2) {
// set alpha for individual images as desired
ctx1.globalAlpha = 0.8;
ctx2.globalAlpha = 0.5;
drawAll();
}
}
function draw1() {
frameRate = 30;
ctx1.clearRect(0, 0, 250, 150);
ctx1.beginPath();
ctx1.rect(0, 0, 250, 150);
ctx1.drawImage(img1, 0, 0); //draw 1st image
ctx1.closePath();
}
function draw2() {
frameRate = 60;
ctx2.clearRect(0, 0, 250, 150);
ctx2.beginPath();
ctx2.rect(0, 0, 250, 150);
ctx2.drawImage(img2, 0, 0); //draw 2nd image
ctx2.closePath();
}
function drawAll() {
draw1();
draw2();
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
#layer1,
#layer2 {
position: absolute;
top: 0;
left: 0;
}
<canvas id="layer1">
</canvas>
<canvas id="layer2">
</canvas>