CanvasRenderingContext2D

时间:2016-04-12 16:08:31

标签: canvas html5-canvas 2d transparency alphablending

有没有办法将多个绘制操作组合到第二个画布渲染上下文,使得它们的组合结果组合到画布的先前内容上,而不是每个绘图操作由自己组成?

一个应用:我想画一个带箭头的半透明线,我想避免在线和箭头重叠的区域增加不透明度。

许多其他渲染模型都支持此类功能。 SVG具有group opacity设置,如第14.5节所述。 PDF reference描述了7.3节中的“透明度组”。在许多图形应用程序中,用户可以构建图层,然后将它们组合成一个整体。

我想我可以设置第二个不可见的画布用作屏幕外图像,将我的内容渲染到那个,然后使用globalAlpha将结果组合到具有所需半透明度的主画布上。但我希望有一些更优雅的解决方案,即使我到目前为止在文档中找不到它。

Merge multiple paths in CanvasRenderingContext2D to fill and stroke as a set显然也有类似的目标。但重点似乎是如何在路径上执行布尔操作,可能就像clipper那样。所以对于这篇文章,我对前面的路径操作并不感兴趣;我希望能够像往常一样绘制每个笔画。

2 个答案:

答案 0 :(得分:2)

不,如果不使用中间画布,目前是不可能的。

除非所涉及的所有绘制操作都可以合并为一个路径,因此只需调用stroke()fill()。我认为这不是这种情况,但后来搜索的人可能正在寻找这些信息。

// two rectangles composed into a single draw operation:
ctx.rect(0, 0, 10, 10);
ctx.rect(5, 5, 10, 10);
ctx.fill();

// With transparency, the above produces a different result from:
ctx.rect(0, 0, 10, 10);
ctx.fill();
ctx.rect(5, 5, 10, 10);
ctx.fill();

答案 1 :(得分:1)

也许是因为我已经习惯了层次的想法,我确实认为离屏画布仍然是最优雅的方式。

但请注意,在空白画布的特殊* 情况下,您还可以在单​​个画布元素上实现它,这要归功于globalCompositeOperation属性。

我们的想法是首先绘制一组不透明的重叠路径,然后使用gCO "destination-in"并绘制一个矩形,覆盖整个区域的颜色 (请参阅评论和编辑后的更好的方法,仍然使用gCO)

var ctx = c.getContext('2d');

// first draw your overlapping paths opaque
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(40, 40, 35, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.arc(60, 60, 35, 0, Math.PI * 2);
ctx.stroke();
// then set the fill color to the one you want
ctx.fillStyle = 'rgba(0,255,0,.5)';
// set the gCo so we only draw on the existing pixels
ctx.globalCompositeOperation = 'source-in';
// draw a large rect
ctx.fillRect(0, 0, c.width, c.height);
p{position: absolute;z-index:-1}
body{background-color: ivory;}
<p>Is this transparent ?</p>
<canvas id="c"></canvas>

* 实际上,我能想到的唯一一个案例就是幕后画布; - )

修改

正如@K3N所述,使用"copy"复合操作,它甚至可以是simplifiedimproved