使用setTransform(1,0,0,1,0,0)vs save()restore()

时间:2019-02-24 13:49:50

标签: animation canvas transform

我使这段代码可以独立旋转/移动两个框,同时保持第三个框静止以确认静态基础变换。在每个转换序列之后未成功应用save()restore()之后,我终于可以通过使用setTransform(1,0,0,1,0,0)使其工作。尽管它现在可以正常工作,但我仍然想知道是否存在正确的保存/恢复顺序来解决问题,而不是重置转换。

<canvas id="ctx" width="500" height="500" style="border:1px solid #000000;"> 
</canvas>

<script>
var ctx = document.getElementById("ctx").getContext("2d");
canvasWidth=500;
canvasHeight=500;

// box 1
var x=250;
var y=250;
var box = 50;
var angle1 = 90;

//box 2
var x2=200;
var y2=200;
var box = 50;
var angle2 = 90;

function rotate() {
angle1-=1;
angle2+=1;

ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.save();

//box 1
x=x-2;
y=y+2;
var ctrX = x+box/2;
var ctrY = y+box/2;

//box 2
x2=x2+.5;
y2=y2+.5;
var ctrX2 = x2+box/2;
var ctrY2 = y2+box/2;

// box 1
ctx.translate(ctrX, ctrY);//-------------------------------- move reg to center 
box
ctx.rotate(angle1 / 60);//----------------------------------rotate
ctx.translate(-ctrX, -ctrY);//-------------------------------- move reg back same 
amt

//------------------------------------------------------- draw
ctx.fillStyle = "blue";
ctx.fillRect(x, y, box, box);
ctx.fillStyle = "red";
ctx.fillRect(x, y, 10, 10);
ctx.fillStyle = "black";
ctx.fillRect(ctrX-5, ctrY-5, 10, 10);

ctx.setTransform(1,0,0,1,0,0);

//-------------------------------------------------------------------- second box
ctx.translate(ctrX2, ctrY2);//-------------------------------- move reg to center 
box
ctx.rotate(angle2 / 60);//----------------------------------rotate
ctx.translate(-ctrX2, -ctrY2);//-------------------------------- move reg back 
same amt

//------------------------------------------------------- draw
ctx.fillStyle = "green";
ctx.fillRect(x2, y2, box, box);
ctx.fillStyle = "red";
ctx.fillRect(x2, y2, 10, 10);
ctx.fillStyle = "black";
ctx.fillRect(ctrX2-5, ctrY2-5, 10, 10);

ctx.setTransform(1,0,0,1,0,0);

ctx.fillStyle = "black";//............................. draw control point
ctx.fillRect(50, 50, 10, 10);
ctx.restore();
}

setInterval(rotate, 100);

</script>

1 个答案:

答案 0 :(得分:0)

重置变换矩阵是必经之路。

save() / restore()保存并恢复您设置的上下文的属性全部;对于内存来说,这是有代价的,并且最终也会对性能造成影响,而重置矩阵会设置上下文的单个属性,这意味着不使用内存。
clip()要求这样做,但是clip()本身应通过使用合成避免。

此外,此方法在您的代码中隐含一种goto()逻辑,并且由于没有明确说明当前状态是什么而使阅读变得更加困难,并且还易于遗漏一个{{ 1}},然后让您的代码造成内存泄漏。

要回答您的问题,您必须了解此操作的工作原理。

我已经说过restore()保存了上下文的所有可设置属性,它将存储在堆栈中,然后save() 弹出要还原的最后一个。

这意味着要能够还原到以前的状态,您至少需要保存与还原所需次数相同的次数。

因此,您可以将所有restore()行替换为

setTransform

或者您可以在游览功能(此处为3)中直接调用ctx.restore(); // apply popped state ctx.save(); // push current (restored) state 多次,

但是无论如何,只要走save()的方式即可。