如何将画布恢复到另一个函数中保存的状态?

kon*_*jac 1 javascript canvas html5-canvas

我想保存在一个函数画布的状态DRAW1() ,它在另一个功能恢复DRAW2() .所以我写了下面的代码.但它不起作用.

<canvas id="canvas" style="width:500px; height:500px;" height="500" width="500"></canvas>
ctx = document.querySelector('#canvas').getContext('2d');
function draw1(){
   ctx.save();
   ctx.fillRect(25,25,100,100);
}
function draw2(){
   ctx.restore();
}
draw1();
draw2();
Run Code Online (Sandbox Code Playgroud)

我想原因是状态保存在调用堆栈中.因此,在函数返回后,还会清除保存状态.

还有其他方式来实现我的需求吗?

UPD:背景是我想实现一个简单的动画,其中大部分都是静态的.我希望使用setInterval()来执行绘图函数draw().在draw()中,首先恢复画布并绘制剩余的动态部分.

Gus*_*lho 5

如果我理解正确你只需要绘制一些静态对象,然后每帧绘制动画对象.

首先,你完全误解了这些saverestore方法,Michael Geary向你展示了原因.此外,markE还会教您toDataURL随时获取画布快照的方法并保存到图像对象中.这是一个强大的功能,但不是你真正想要的简单动画.

那么,如何使用静态和动态对象创建动画?

如何使用静态和动态对象创建动画

有两个主要选择:

  1. 使用单个画布并绘制动画的每个帧(静态和动态),这可能不是最适合您的,因为大多数对象都是静态的.
  2. 拥有静态对象的画布和动态对象的另一个画布.使用这种技术,你只需要绘制一次静态对象并在那里忘记它(不需要"恢复"你的画布),我们在一个单独的画布中执行动画(每帧绘制动态对象).

我觉得最适合你的是选项2.好的,但是我们如何设置这些画布?

使用多个画布作为图层

使用CSS将所有画布设置为父div标记内的绝对位置(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>
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)