什么是 Canvas.save 和 Canvas.restore?

What is Canvas.save and Canvas.restore?

我在想why and when you would use Canvas.save, Canvas.restore, and maybe even Canvas.saveLayer
听说很好用,就是不知道什么时候用。

Canvas.saveCanvas.saveLayer 的工作方式略有不同,但它们都有相同的对应物:

Canvas.restore

这允许您恢复保存堆栈上最近条目之前的状态,即它“弹出当前保存堆栈”。这意味着在当前状态下对 canvas 所做的任何转换和剪辑都将被删除,如果使用了 saveLayer,保存的图层将被合成到 canvas(绘制顺序将保持不变)。

Canvas.save

正如我之前提到的,这允许您保存 canvas 所处的状态。您可以执行任何 transformationclips 你想要的,那些将被删除使用 restore:

canvas.save();

canvas.transform(..); // Transforms the canvas, which will affect the draw call.
canvas.drawRect(...); // Affected by the transform.

canvas.restore();

canvas.drawRect(...); // Not affected by the transform.

您可以在 restore 之前使用任意数量的 save 并且堆栈将记住所有条目,即 restore 将始终弹出最近的条目。

我什么时候用这个?

例子:如果你想在画大图的时候旋转一个单块,你可以简单地在save-restore块内旋转,然后在上面画一些没有旋转的东西.

注意一个RenderObject的所有children将使用相同的PaintingContext,即相同的Canvas。因此,如果您在单个 child 中转换 canvas,它也会为之后绘制的所有其他 children 进行转换。这可能是不需要的行为,也是您总是希望 saverestore 处于 canvas 状态的原因。

Canvas.saveLayer

这有点复杂,我强烈建议您阅读此方法的综合文档。顺便说一句,saveLayer does not work in Flutter web as of January, 2019.

saveLayersave 的基本区别在于 saveLayer 将在使用 restore 时合成图层。举个简单的例子,我构建了这个片段 without bounds (这就是 null 被传递的原因),它将保存整个 canvas:

canvas.drawRect(rect, Paint()..color = const Color(0xffff0000)); // Draws a red rect.
canvas.saveLayer(null, Paint()..blendMode = BlendMode.multiply); // Saves the whole canvas.

canvas.drawRect(
  rect.shift(const Offset(20, 20)),
  Paint()..color = const Color(0xff0000ff), // Draws a blue rect.
);

canvas.restore(); // Composites the red rect into the blue rect.

请注意,蓝色矩形仍将合成在红色矩形上方。

这个例子也可以在不使用 saveLayer 的情况下实现,因为 Paint.blendMode I used can also be passed to Canvas.drawRect. However, when using e.g. a TextPainter,你不能通过混合模式。此外,saveLayer 允许您传递边界,这提供了更多可能性(阅读文档以获取更多信息,还有关于 clips 的信息) . 剪辑 实际上可能是与 saveLayer 结合使用时最有用的操作 - 我没有包括它是为了有一个简单的例子。

如果没有 saveLayer:

,示例将是这样的