我有一些浮动云和下降框的画布动画:
var canvas, canvas_overlay, context, ctx_overlay, clouds,
docWidth, docHeight, img_box, img_cloud1, img_cloud2, img_cloud3, img_ground;
img_box = new Image();
img_cloud1 = new Image();
img_cloud2 = new Image();
img_cloud3 = new Image();
img_ground = new Image();
img_box.src = 'images/gift_box_small.png';
img_cloud1.src = 'images/cloud1.png';
img_cloud2.src = 'images/cloud2.png';
img_cloud3.src = 'images/cloud3.png';
img_ground.src = 'images/ground_pattern_small.jpg';
var mustBeReadyCount = 6; // must load image and window
img_box.onload = launchWhenReady;
img_cloud1.onload = launchWhenReady;
img_cloud2.onload = launchWhenReady;
img_cloud3.onload = launchWhenReady;
img_ground.onload = launchWhenReady;
window.onload = launchWhenReady;
function launchWhenReady() {
mustBeReadyCount--;
if (mustBeReadyCount) return;
init();
};
function init(){
docWidth = window.innerWidth;
docHeight = window.innerHeight;
canvas = document.getElementById('canvas');
canvas_overlay = document.getElementById('canvas_overlay');
context = canvas.getContext('2d');
ctx_overlay = canvas_overlay.getContext('2d');
resizeCanvas(docWidth, docHeight);
drawGround();
var cloud1 = new Cloud(0, 10, docWidth, docHeight, img_cloud1, 3, 24);
var cloud2 = new Cloud(Math.floor(docWidth/4*3), 48, docWidth, docHeight, img_cloud2, 5, 24);
var cloud3 = new Cloud(Math.floor(docWidth/2), 90, docWidth, docHeight, img_cloud3, 1, 24);
clouds = [cloud1, cloud2, cloud3];
boxAnimationData.animationStep = 'falling';
boxAnimationData.bounceHeight = (docHeight / 2 - img_box.height)-25;
setInterval(createAnimations, 24);
}
var animationStep = '';
var boxAnimationData = {
animationStep: '',
y: 0-img_box.naturalHeight,
maxY: 0,
bounceCount: 10,
direction: -1,
bounceHeight: 0
};
window.onresize = function(){
init();
}
function resizeCanvas(width, height){
canvas.width = canvas_overlay.width = docWidth;
canvas.height = canvas_overlay.height = docHeight;
}
function drawGround(){
var pattern=context.createPattern(img_ground,"repeat");
context.rect(0,docHeight-50,docWidth,50);
context.fillStyle=pattern;
context.fill();
}
function drawClouds(clouds, width, height){
var img;
var arrLength = clouds.length;
context.clearRect(0,0,width,height-50);
for(var i=0; i<arrLength; i++){
var cloud = clouds[i];
img = cloud.getFilename();
imageWidth = img.naturalWidth;
imageHeight = img.naturalHeight;
context.drawImage(img, cloud.getX()-imageWidth, cloud.getY());
clouds[i].moveCloud(imageWidth);
}
}
function createAnimations() {
drawClouds(clouds, docWidth, docHeight);
if (boxAnimationData.animationStep == 'falling') dropBox();
else if (boxAnimationData.animationStep == 'bouncing') bounceBox();
}
function dropBox() {
ctx_overlay.clearRect(0, 0, docWidth, docHeight);
boxAnimationData.y += 3;
if (boxAnimationData.y + img_box.height + 25 > docHeight) {
boxAnimationData.animationStep = 'bouncing';
}
ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}
function bounceBox() {
ctx_overlay.clearRect(0, 0, docWidth, docHeight);
boxAnimationData.y += boxAnimationData.direction * 3;
if (boxAnimationData.y + img_box.height + 25 > docHeight) {
// reached floor? swap direction
boxAnimationData.direction *= -1;
// and reduce jump height
boxAnimationData.bounceHeight *= 10 / 9;
boxAnimationData.bounceCount--;
if (!boxAnimationData.bounceCount) boxAnimationData.animationStep = '';
} else if (boxAnimationData.y < boxAnimationData.bounceHeight) {
boxAnimationData.direction *= -1;
}
ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}
function Cloud (x, y, width, height, filename, velocity, rate) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.filename = filename;
this.velocity = velocity;
this.rate = rate;
}
Cloud.prototype = {
constructor:Cloud,
moveCloud:function(imageWidth){
if(this.x >= this.width+imageWidth){
this.x=0-imageWidth/2;
} else {
this.x += this.velocity;
}
},
getFilename:function(){
return this.filename;
},
getX:function(){
return this.x;
},
getY:function(){
return this.y;
}
}
您可以在此处观看:http://jsfiddle.net/f2pd36yq/
当调整窗口大小(浏览器窗口或移动设备更改方向)时,我要么重新启动动画,要么最好从同一点继续,但云和框应该获得新文档宽度和高度。此外,如果框已经停在底部,则不应再次设置动画。但我现在所拥有的是一些奇怪的动画在调整窗口大小时加速。
为什么会发生这种情况?如何解决?
答案 0 :(得分:1)
每次调整大小时都会触发init
函数,因此每次调整大小事件时都会再次触发函数底部的setInterval(createAnimations, 24);
。
要解决此问题,只需将setInterval
移至init
函数之外,或仅在实际初始化时调用init
并使用以下内容更新其他变量调整大小时的单独功能
答案 1 :(得分:0)
我遇到了同样的问题,但实现方式不同, 我只是通过在窗口调整大小上调用 requestAnimationFrame(render) 而不是函数本身来解决它
function render {
...
}
requestAnimationFrame(render)
window.addEventListener('resize', requestAnimationFrame(render))
它会将渲染功能添加到animationFrame堆栈中,并且不会加速场景本身