保存多个状态并恢复到每个状态

try*_*sis 5 html javascript canvas

HTML5<canvas>元件具有一种节省状态的机制,通过反复调用cxt.save()和cxt.restore(),其中cxt是<canvas>的‘上下文’,由得到,例如,调用document.getElementById('my-canvas')。但是,我还没有看到一次保存/恢复到多个状态的方法。似乎可以<canvas>访问多个状态,因为restore多次调用会恢复每个各自的“最后”保存状态。

有没有办法在不restore多次调用的情况下跳回到“最后”状态之前?另外,有没有办法通过各州“前进”?如果我们可以给每个州一个名称,这可能会更容易做到,但如果需要,我可以使用 ID。最后它可能看起来类似于 Adob​​e Photoshop 的“图层”概念。

我也会采取一个答案,将每个状态保存到不同的变量,或者可以复制上下文而不创建一个全新的<canvas>. 像angular.copy这样的复制函数似乎不适用于上下文,可能是因为它们在技术上不是对象;我相信它们继承自接口。

最后,这是否有效?我知道图形密集<canvas>程度如何,它对客户端计算机的负担有多大。有没有比实现分层系统更好的方法来操纵上下文而不破坏画布的其他部分?

mar*_*rkE 5

一些背景:

context.save并context.restore保存和恢复上下文状态。上下文状态包括样式、转换、合成等。

.save将当前状态压入栈顶。.restore将从堆栈顶部弹出最后添加的状态。因此,它们充当后进先出状态堆栈。

您可以执行多个操作.save,将多个状态推送到堆栈上。然后你可以通过执行 multiple 从堆栈中弹出多个状态.restore。

由于.save将保存所有上下文状态,因此保存和恢复是相对昂贵的操作。

多个保存/恢复的示例:

context.fillStyle='red';
context.fillRect(0,0,10,10);    // red rectangle
context.save();                 // fillStyle=='red'
context.fillStyle='blue';       // fillStyle='blue'
context.fillRect(0,0,10,10);    // blue rectangle
context.save();                 // fillStyle=='blue'
context.fillStyle='green';      // fillStyle=='green'
context.fillRect(0,0,10,10);    // green rectangle
context.restore();              // fillStyle='blue';
context.fillRect(0,0,10,10);    // blue rectangle
context.restore();              // fillStyle='red'
context.fillRect(0,0,10,10);    // red rectangle
Run Code Online (Sandbox Code Playgroud)

答案#1:不,没有办法在不执行多次恢复的情况下回归到之前保存的状态。状态保存在堆栈中,因此与状态数组不同,您无法“跳转”到状态 [2]。

答案#2:在实践中,更常见的是不使用保存/恢复,而是使用 javascript 对象根据需要存储最少的状态信息。

例如:

// put various fillStyles in a fills object
var fills={};
fills.red='red';
fills.green='green';
fills.blue='blue';

// create a function that draws a rect with specified fillStyle
function styledRect(x,y,w,h,fill){
    var priorFill=context.fillStyle;
    context.fillStyle=fill;
    context.fillRect(x,y,w,h);
    context.fillStyle=priorFill;
}

// use the fills object to control the fillStyle "state"
styledRect(0,0,10,10,fills.red);
Run Code Online (Sandbox Code Playgroud)

更复杂的“状态”对象可能如下所示:

buttonStyles={};
buttonStyles.normal={ font:'12px verdana', fill:'black' };
buttonStyles.warning={font:'12px italic verdana', fill:'orange' };
buttonStyles.danger={ font:'14px italic verdana', fill:'red' };

// example usage
someButtonDrawingFunction("You're in danger!",buttonStyles.danger);
Run Code Online (Sandbox Code Playgroud)