如何在HTML5画布中使用alpha = 0绘制以“擦除”为目的

3

如何在HTML5画布上使用alpha = 0绘图?假设我正在制作一个Photoshop克隆版,我有一个纯红色的图层。我选择橡皮擦工具并开始绘图。它以rgba(0,0,0,0)的方式绘制,让我能够看到背景。在HTML5画布上如何实现这一点?

以下是一些代码。

var rand = function(v) {
    return Math.random() * v;
};

var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext("2d");

// fill the canvas with black
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Erase some circles (draw them in 0,0,0,0);
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.globalCompositeOperation = "copy";
for (var ii = 0; ii < 5; ++ii) {
    ctx.beginPath();
    ctx.arc(rand(canvas.width), rand(canvas.height), 
            rand(50) + 20, 0, 360, false);
    ctx.fill();
}

/*
source-over    
source-in    
source-out    
source-atop

destination-over    
destination-in    
destination-out    
destination-atop

lighter    
darker    
copy    
xor
*/
canvas {
    margin: 10px;
    border: 1px solid black;
    background-color: yellow;
}
<div>Want red with yellow circles</div>
<canvas></canvas>

这不起作用。所有画布操作都被认为是无限大的,这意味着将每个圆(弧线)的globalCompositeOperation设置为"copy"会有效地擦除每个圆外部的所有内容。

我可能能够设置剪辑以匹配圆形,但理想情况下,我想用抗锯齿圆形擦除,就像Photoshop画笔一样。

3个回答

5
你需要使用以下内容:

你需要使用:

ctx.fillStyle = "rgba(0,0,0,1)"; // (Drawing with 0 alpha pretty much means doing nothing)
ctx.globalCompositeOperation = "destination-out";

工作示例

请记住保存以前的globalCompositeOperation并恢复它,否则透明度会在后续操作中失效。

问题在于,“在画布上使用alpha=0绘图默认只会覆盖一层不可见的“墨水”。”


你能解释一下它是如何工作的吗?在我的fiddle中,画布在绘制“擦除”圆之前是255,0,0,255。rgba(0,0,0,1)=0,0,0,255。那么alpha值是如何变成0的呢?它似乎只有两个选择,即从源处获取255或从目标处获取255。 - gman
你是怎么理解 "alpha 怎么变成 0?" 的?你是指画布位置 X 处的 alpha 变成了 0 吗?如果是这样,那就是 globalCompositeOperation 的工作原理。使用 "destination-out" 时,它会从现有画布中 "切割" 出绘制形状。 - Cerbrus
这里有一个更好的链接:(https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Compositing) - Cerbrus

0
如果您想要流畅地擦除,那么当鼠标被点击并移动时,这条线就应该被擦除,这可能是一个解决方案:
var canvas = document.getElementById("myCanvas");
var eraseWidth = 5;

$("#myCanvas").mousedown(function(canvas){          //the mousedown (writing) handler, this handler does not draw, it detects if the mouse is down (see mousemove)
    x = canvas.pageX-this.offsetLeft;
    y = canvas.pageY-this.offsetTop;
});

$("#myCanvas").mousemove(function(canvas){
    context.beginPath();
    var x2 = x-(eraseWidth/2);          //x2 is used to center the erased rectangle at the mouse point
    var y2 = y-(eraseWidth/2);          //y2 is used to center the erased rectangle at the mouse point
    context.clearRect(x2, y2, eraseWidth, eraseWidth);              //clear the rectangle at the mouse point (x2 and y2)
    context.closePath();
};

基本上,它的作用是在移动鼠标时清除一个矩形,每次鼠标处理程序发送鼠标移动事件并使用画布中心的x和y坐标来清除矩形。结果是一条已清除的线。
好吧,如果你移动得太快就会看到矩形,但我的项目只是一个概念,所以对我来说这很有效 ;)

0
如果你正在开发类似于 Photoshop 的软件,那么最好为每个图层创建一个画布。我认为这会极大地简化你的工作,同时也能提高性能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接