如何将画布恢复到另一个函数中保存的状态? [英] How to restore a canvas to status saved in another function?

查看:201
本文介绍了如何将画布恢复到另一个函数中保存的状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将画布的状态保存在函数 draw1()中,并在另一个函数 draw2()中恢复。所以我写了以下代码。但它不工作。

I want to save the status of a canvas in a function draw1(), and restore it in another function draw2(). So I wrote following code. But it doesn't work.

<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();



我猜这是因为状态保存在调用堆栈中。

I guess the reason is that the status is saved in the call stack. So after the function returns, the saving state is also cleared.

有没有其他方法来实现我的需要?

Is there other way to implement my need?

UPD:背景是我想实现一个简单的动画,其中大部分是静态的。我希望使用 setInterval()来执行绘图函数 draw()

UPD: The background is that I want to implement a simple animation, most of which are static. I expect to use setInterval() to execute a drawing function draw(). In draw(), restore the canvas back first and draw the remaining dynamic part.

推荐答案

draw()我明白你只需要绘制一些静态对象一次,然后在每一帧绘制动画对象。

If I understand right you only need to draw some static objects once and then draw the animated objects each frame.

首先,你完全误解了 save restore 方法和Michael Geary向您展示了为什么。此外,markE教你使用 toDataURL 方法随时拍摄画布的快照并保存到图像对象中。

First off all, you completely misunderstood the save and restore methods and Michael Geary showed you why. Also markE teaches you the toDataURL method for take snapshots of your canvas at any time and save into an image object. It's a powerful feature, but isn't what you really want for simple animations.

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

So, how do I create animations with static and dynamic objects?

有两个主要选项:


  1. 使用单个画布,并绘制动画的每个帧的所有对象(静态和动态),这可能不是最好的,因为大多数对象是静态的。

  2. 为静态对象创建画布,为动态对象创建另一个画布。使用这个技术你只需要绘制静态对象一次,忘记它(不需要恢复你的画布),我们在一个单独的画布中执行动画(每个框架绘制动态对象)。

  1. Using one single canvas and draw all objects (static and dynamic) each frame of your animation, which probably is not the best for you since most of your objects are static.
  2. Have a canvas for static objects and another canvas for dynamic objects. Using this technic you only need to draw the static objects once and forget it there (no need for "restore" your canvas) and we perform the animations (drawing dynamic objects each frame) in a separated canvas.

我认为最好的选择是选项2.好的,但我们如何设置这些画布?

I think the best for you will be option 2. Ok, but how we setup those canvases?

使用CSS将所有画布设置为绝对位置0)在 div 标签内。

Use CSS to set all the canvases to an absolute position of (0,0) inside our parent div tag.

同样使用CSS来设置我们的画布的z-索引。 z-index属性指定元素的堆栈顺序。

Also use CSS to set the z-index of our canvases. The z-index property specifies the stack order of an element. Items with lower z-index values go behind items with higher z-index values.

现在我们正确定义了我们的画布,让我们玩!

Now that we properly define our canvases, let's play!

我制作了一个jsFiddle,向您展示如何完成所需的动画。

I made a jsFiddle to show you how to accomplish the desired animations.

检查小提琴

及其中使用的代码fiddle:

and the code used in that fiddle:

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:

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

这篇关于如何将画布恢复到另一个函数中保存的状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆