如果我理解正确,您只需要绘制一次静态对象,然后每帧绘制动画对象。
首先,您完全误解了save
和restore
方法,Michael Geary 向您展示了原因。markE还教您toDataURL
随时拍摄画布快照并保存到图像对象中的方法。这是一个强大的功能,但不是您真正想要的简单动画。
那么,如何使用静态和动态对象创建动画呢?
如何使用静态和动态对象创建动画
有两个主要选项:
- 使用一个画布并在动画的每一帧中绘制所有对象(静态和动态),这对您来说可能不是最好的,因为您的大多数对象都是静态的。
- 有一个用于静态对象的画布和另一个用于动态对象的画布。使用这种技术,您只需要绘制一次静态对象并忘记它(无需“恢复”您的画布),我们在单独的画布中执行动画(每帧绘制动态对象)。
我认为最适合您的是选项 2。好的,但是我们如何设置这些画布?
使用多个画布作为图层
div
使用 CSS 将所有画布设置为父标签内 (0,0) 的绝对位置。
还使用 CSS 设置画布的 z-index。z-index 属性指定元素的堆叠顺序。具有较低 z-index 值的项目位于具有较高 z-index 值的项目之后。
现在我们正确定义了画布,让我们开始吧!
演示
我制作了一个 jsFiddle 来向您展示如何完成所需的动画。
检查小提琴
以及该小提琴中使用的代码:
HTML:
<div id="canvasesdiv">
<canvas id="static" width=400 height=400>This text is displayed if your browser does not support HTML5 Canvas</canvas>
<canvas id="dynamic" width=400 height=400>This text is displayed if your browser does not support HTML5 Canvas</canvas>
</div>
CSS:
#canvasesdiv {
position:relative;
width:400px;
height:300px;
}
#static {
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
#dynamic {
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
Javascript:
// static canvas
var static = document.getElementById("static");
var staticCtx = static.getContext("2d");
// dynamic canvas
var dynamic = document.getElementById("dynamic");
var dynamicCtx = dynamic.getContext("2d");
// animation status
var FPS = 30;
var INTERVAL = 1000 / FPS;
// our background
var myStaticObject = {
x: 0,
y: 0,
width: static.width,
height: static.height,
draw: function () {
staticCtx.fillStyle = "rgb(100, 100, 0)";
staticCtx.fillRect(0, 0, static.width, static.height);
}
};
// our bouncing rectangle
var myDynamicObject = {
x: 30,
y: 30,
width: 50,
height: 50,
gravity: 0.98,
elasticity: 0.90,
friction: 0.1,
velX: 10,
velY: 0,
bouncingY: false,
bouncingX: false,
draw: function () { // example of dynamic animation code
// clear the last draw of this object
dynamicCtx.clearRect(this.x - 1, this.y - 1, this.width + 2, this.height + 2);
// compute gravity
this.velY += this.gravity;
// bounce Y
if (!this.bouncingY && this.y >= dynamic.height - this.height) {
this.bouncingY = true;
this.y = dynamic.height - this.height;
this.velY = -(this.velY * this.elasticity);
} else {
this.bouncingY = false;
}
// bounce X
if (!this.bouncingX && (this.x >= dynamic.width - this.width) || this.x <= 0) {
this.bouncingX = true;
this.x = (this.x < 0 ? 0 : dynamic.width - this.width);
this.velX = -(this.velX * this.elasticity);
} else {
this.bouncingX = false;
}
// compute new position
this.x += this.velX;
this.y += this.velY;
// render the object
dynamicCtx.fillStyle = "rgb(150, 100, 170)";
dynamicCtx.fillRect(this.x, this.y, this.width, this.height);
}
};
function drawStatic() {
myStaticObject.draw();
// you can add more static objects and draw here
}
function drawDynamic() {
myDynamicObject.draw();
// you can add more dynamic objects and draw here
}
function animate() {
setInterval(function () {
// only need to redraw dynamic objects
drawDynamic();
}, INTERVAL);
}
drawStatic(); // draw the static objects
animate(); // entry point for animated (dynamic) objects