画布剪裁区域和画布堆栈

时间:2016-05-13 14:36:56

标签: javascript html5 canvas html5-canvas

我已经开始研究O'Reilly的书“HTML5 Canvas”。我在第二章,其中一个例子提供的代码没有得到很好的解释。例2-5:

  1. 画一个黑盒子
  2. 推送状态
  3. 在左上角设置小剪裁区域
  4. 画圆圈
  5. pop state
  6. 设置大剪裁区域
  7. 画另一个圈子
  8. 但是我无法理解一些事情:

    context.fillStyle = 'black';
    context.fillRect(10, 10, 200, 200);
    
    context.save();
    
    context.beginPath();
    context.rect(0, 0, 50, 50);
    context.clip();
    
    context.beginPath();
    context.strokeStyle = 'red';
    context.lineWidth = 5;
    context.arc(100, 100, 100, 0, 2*Math.PI, false);
    context.stroke();
    context.closePath();
    
    context.restore();
    
    context.beginPath();
    context.rect(0, 0, 500, 500);
    context.clip();
    
    context.beginPath();
    context.strokeStyle = 'blue';
    context.lineWidth = 5;
    context.arc(100, 100, 50, 0, 2*Math.PI, false);
    context.stroke();
    context.closePath();
    

    我的问题:

    首先,context.clip()是否隐式关闭了上下文路径(“context.closePath()”)?它前面是context.beginPath(),后跟另一个context.beginPath()。像这样:

    context.beginPath();
    context.rect(0, 0, 50, 50);
    context.clip();
    context.beginPath();
    

    其次,为什么有必要推动上下文状态?为什么我不能只改变裁剪区域?这似乎是必要的,因为没有推动国家就行不通。如果我没有推动状态然后恢复它,那么大的蓝色圆圈就不会出现了,我不明白为什么。

1 个答案:

答案 0 :(得分:3)

  

context.clip()是否隐式关闭了上下文路径?...
  它前面是context.beginPath(),后跟另一个context.beginPath()。像这样:[...]

是的,这是创建剪切所需的近似形状的唯一方法,因此如果未调用closePath(),clip()将在内部关闭路径。

specification states:

  

在计算剪切区域时,必须隐式关闭打开的子路径,而不会影响实际的子路径。

beginPath()将清除当前主路径及其所有子路径。剪辑仍然处于活动状态,但现在您可以执行其他路径操作,这些操作在栅格化时会受到剪辑区域的影响。

  

为什么需要推送上下文状态?

虽然已经建议并讨论过(但标准中有resetClip()但尚未得到广泛支持),因此无法重置剪辑区域。 Calling clip()几次 -

  

clip()方法必须通过计算当前剪切区域的交集来创建新的剪切区域[...]

换句话说,如果我们说为整个绘图表面定义了一个剪辑区域,它就不会被替换。

因此我们删除剪辑的唯一方法是保存状态,设置剪辑然后恢复以删除它。