canvas 精灵 sheet 错误
canvas sprite sheet error
我在 canvas spritesheet 动画上找到了一个可爱的代码片段。这是 ts:
http://jsfiddle.net/m1erickson/h85Gq/
我试图通过编写一个接受 Image 对象的动画函数来美化这段代码,这样我就可以同时在 canvas 中为多个图像制作动画。这是我的尝试:
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var spritePosition=0;
var spriteWidth=100;
var spriteHeight=100;
var spriteCount=40;
var spritePlayCount=0;
var maxSpritePlays=2;
var objectS=new Image();
objectS.src="sprites/first.png";
var fps = 50;
function animate(sprite) {
setTimeout(function() {
if(spritePlayCount<maxSpritePlays){
requestAnimationFrame(animate);
}
// Drawing code goes here
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(sprite,spritePosition*spriteWidth, 0,spriteWidth, spriteHeight, 0,0,spriteWidth, spriteHeight);
spritePosition++;
if(spritePosition>spriteCount-1){
spritePosition=0;
spritePlayCount++;
}
}, 1000 / fps);
}
objectS.onload=function(){
animate(objectS);
}
}); // end $(function(){});
我发现了一个很常见的错误,但我似乎找不到解决方法:
index3.html:59 Uncaught TypeError: Failed to execute 'drawImage' on
'CanvasRenderingContext2D': The provided value is not of type
'(CSSImageValue or HTMLImageElement or HTMLVideoElement or
HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
你能帮我找出我的错误吗?
使用requestAnimationFrame调用animate函数时,您还需要传递sprite
参数。
$(function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var spritePosition = 0;
var spriteWidth = 100;
var spriteHeight = 100;
var spriteCount = 40;
var spritePlayCount = 0;
var maxSpritePlays = 2;
var objectS = new Image();
objectS.src = "sprites/first.png";
var fps = 50;
function animate(sprite) {
setTimeout(function() {
if (spritePlayCount < maxSpritePlays) {
requestAnimationFrame(function() {
animate(sprite);
});
}
// Drawing code goes here
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(sprite, spritePosition * spriteWidth, 0, spriteWidth, spriteHeight, 0, 0, spriteWidth, spriteHeight);
spritePosition++;
if (spritePosition > spriteCount - 1) {
spritePosition = 0;
spritePlayCount++;
}
}, 1000 / fps);
}
objectS.onload = function() {
animate(objectS);
};
});
天啊!
quote OP "Imagine having 50 spritesheets you want to animate."
50!
查看代码“接受的答案版本”
function animate(sprite) {
// create a timer event to fire in 1/50th second
setTimeout(function() {
if (spritePlayCount < maxSpritePlays) {
// create a animation frame event that may fire at some time
// between 0 and 16ms or 32ms from now
requestAnimationFrame(function() {
animate(sprite);
});
}
// Drawing code etc... Make canvas dirty
// exiting with dirty canvas outside the requestAnimationFrame
// forces DOM to swap canvas backbuffer immediately on exit.
}, 1000 / 50);
}
这是制作一个精灵的最糟糕的方法,更不用说多个精灵了。
- 时间与显示刷新不同步。
- 使用requestAnimationFrame的回调创建定时事件渲染,完全否定了使用requestAnimationFrame的理由。 requestAnimationFrame 告诉 DOM 您在回调中绘制的内容是动画的一部分。使用计时器绘制意味着您不会在请求的帧中绘制任何内容,从而使请求变得多余。
- requestAnimationFrame 尽最大努力在下一次显示刷新(1/60)之前获取所有回调,但如果没有时间更新 DOM(交换所有脏缓冲区),它将延迟回调在下一次刷新之前。您无法控制动画的时间,它们可能会在 20 毫秒到 36 毫秒或更长的任何时间触发,并且随着时间的推移没有一致性。
- 通过使用计时器绘制到 canvas,您将强制为您绘制的每个 sprite 进行后台缓冲区交换。这是一个昂贵的过程,会严重限制您绘制精灵的速度,并导致精灵在动画期间随机闪烁和剪切。
最佳实践方式。
- 使用由 requestAnimationFrame 触发的单个动画循环。
- 使用数组存储所有精灵并在主循环中更新它们if/as 需要。
- 仅从主循环内渲染。不要在主循环执行之外渲染或对 DOM 执行任何操作(定期)。
- 不要呈现计时器、IO 或任何其他快速触发事件等内部事件。
我在 canvas spritesheet 动画上找到了一个可爱的代码片段。这是 ts:
http://jsfiddle.net/m1erickson/h85Gq/
我试图通过编写一个接受 Image 对象的动画函数来美化这段代码,这样我就可以同时在 canvas 中为多个图像制作动画。这是我的尝试:
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var spritePosition=0;
var spriteWidth=100;
var spriteHeight=100;
var spriteCount=40;
var spritePlayCount=0;
var maxSpritePlays=2;
var objectS=new Image();
objectS.src="sprites/first.png";
var fps = 50;
function animate(sprite) {
setTimeout(function() {
if(spritePlayCount<maxSpritePlays){
requestAnimationFrame(animate);
}
// Drawing code goes here
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(sprite,spritePosition*spriteWidth, 0,spriteWidth, spriteHeight, 0,0,spriteWidth, spriteHeight);
spritePosition++;
if(spritePosition>spriteCount-1){
spritePosition=0;
spritePlayCount++;
}
}, 1000 / fps);
}
objectS.onload=function(){
animate(objectS);
}
}); // end $(function(){});
我发现了一个很常见的错误,但我似乎找不到解决方法:
index3.html:59 Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
你能帮我找出我的错误吗?
使用requestAnimationFrame调用animate函数时,您还需要传递sprite
参数。
$(function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var spritePosition = 0;
var spriteWidth = 100;
var spriteHeight = 100;
var spriteCount = 40;
var spritePlayCount = 0;
var maxSpritePlays = 2;
var objectS = new Image();
objectS.src = "sprites/first.png";
var fps = 50;
function animate(sprite) {
setTimeout(function() {
if (spritePlayCount < maxSpritePlays) {
requestAnimationFrame(function() {
animate(sprite);
});
}
// Drawing code goes here
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(sprite, spritePosition * spriteWidth, 0, spriteWidth, spriteHeight, 0, 0, spriteWidth, spriteHeight);
spritePosition++;
if (spritePosition > spriteCount - 1) {
spritePosition = 0;
spritePlayCount++;
}
}, 1000 / fps);
}
objectS.onload = function() {
animate(objectS);
};
});
天啊!
quote OP "Imagine having 50 spritesheets you want to animate."
50!
查看代码“接受的答案版本”
function animate(sprite) {
// create a timer event to fire in 1/50th second
setTimeout(function() {
if (spritePlayCount < maxSpritePlays) {
// create a animation frame event that may fire at some time
// between 0 and 16ms or 32ms from now
requestAnimationFrame(function() {
animate(sprite);
});
}
// Drawing code etc... Make canvas dirty
// exiting with dirty canvas outside the requestAnimationFrame
// forces DOM to swap canvas backbuffer immediately on exit.
}, 1000 / 50);
}
这是制作一个精灵的最糟糕的方法,更不用说多个精灵了。
- 时间与显示刷新不同步。
- 使用requestAnimationFrame的回调创建定时事件渲染,完全否定了使用requestAnimationFrame的理由。 requestAnimationFrame 告诉 DOM 您在回调中绘制的内容是动画的一部分。使用计时器绘制意味着您不会在请求的帧中绘制任何内容,从而使请求变得多余。
- requestAnimationFrame 尽最大努力在下一次显示刷新(1/60)之前获取所有回调,但如果没有时间更新 DOM(交换所有脏缓冲区),它将延迟回调在下一次刷新之前。您无法控制动画的时间,它们可能会在 20 毫秒到 36 毫秒或更长的任何时间触发,并且随着时间的推移没有一致性。
- 通过使用计时器绘制到 canvas,您将强制为您绘制的每个 sprite 进行后台缓冲区交换。这是一个昂贵的过程,会严重限制您绘制精灵的速度,并导致精灵在动画期间随机闪烁和剪切。
最佳实践方式。
- 使用由 requestAnimationFrame 触发的单个动画循环。
- 使用数组存储所有精灵并在主循环中更新它们if/as 需要。
- 仅从主循环内渲染。不要在主循环执行之外渲染或对 DOM 执行任何操作(定期)。
- 不要呈现计时器、IO 或任何其他快速触发事件等内部事件。