我有一个 HTML5 画布。我正在使用KineticJS(KonvaJS)画布库。在空白画布上,我绘制了如下图所示的图像。现在我想创建一个圆形,可以用来擦除图像的一部分。图中红色圆圈为橡皮擦。
如何擦除 HTML5 Canvas 上的部分图像?
我有一个 HTML5 画布。我正在使用KineticJS(KonvaJS)画布库。在空白画布上,我绘制了如下图所示的图像。现在我想创建一个圆形,可以用来擦除图像的一部分。图中红色圆圈为橡皮擦。
如何擦除 HTML5 Canvas 上的部分图像?
您可以使用合成来“擦除”像素。
具体来说,您使用destination-out
合成。
KineticJS 不支持合成,但您仍然有几个选择:
(注:KineticJS 已经变成了 KonvaJS,我还没有检查 KonvaJs 是否支持合成。如果现在支持,只需destination-out
在 KonvaJS 中使用合成)
选项#1:使用原生画布元素作为 Kinetic.Image 源
使用创建内存中的 html5 画布var c=document.createElement
,
将画布调整为图像大小,
drawImage
你的图像到画布上,
创建一个Kinetic.Image
并将其图像属性设置为对本机画布的引用。Kinetic.Image 将显示在本机画布上绘制的任何内容。
var kImage=new Kinetic.Image({
...
image:c,
...
设置画布合成以使新绘图“擦除”现有像素:
c.globalCompositeOperation='destination-out';
监听圆形橡皮擦上的拖动事件。使用这些事件在画布上绘制一个圆圈,该圆圈的移动就像 Kinetic 圆形橡皮擦的移动一样。由于画布的合成设置为“擦除”,画布上新绘制的圆圈将擦除画布上的图像。
您的 Kinetic.Image 准确地反映了它的画布源 (var c),因此您的 Kinetic.Image 还将显示正在擦除的图像以响应 Kinetic 圆形橡皮擦的移动。
选项#2:使用 Kinetic.Shape
您可以通过在单独的图层上创建 Kinetic.Shape 并使用以下方法获取对本机画布上下文的引用来执行与 Option#1 相同的操作:
var ctx = myShapeLayer.getContext()._context;
这是一个较弱的选项,因为 KineticJS 将重新绘制形状——导致您的擦除被撤消。因此,您必须执行额外的步骤,即保存所有圆形橡皮擦的动作并重播这些动作(在 中drawFunc
)以重新擦除。
感谢markE的详细回答,
我试图从中获取上下文Konva.Layer()
并且它起作用了。
var freeHandDrawingImage = new Image();
freeHandDrawingImage.onload = function() {
var context = freeHandDrawingLayer.getContext('2d');
context.drawImage(this, 0,0);
context.globalCompositeOperation='destination-out';
freeHandDrawingLayer.draw();
};
freeHandDrawingImage.src = "image.png";
我已经使用自定义Konva.Shape
擦除"destination-out"
和绘制自由绘制"source-over"
:
freeDrawingType = 'brush';
isFreeDrawingMode = false;
isPaint = false;
lastPointerPosition = {};
drawFreeDrawings = function(){
var freeDraw = new Konva.Shape({
name: "freeDraw",
stroke: 'black',
strokeWidth: 5,
closed : false,
sceneFunc: function(context){
// free draw quad
debugger;
if(isPaint){
if (freeDrawingType === 'brush') {
context.globalCompositeOperation = 'source-over';
}
if (freeDrawingType === 'eraser') {
context.globalCompositeOperation = 'destination-out';
}
context.beginPath();
context.moveTo(lastPointerPosition.x, lastPointerPosition.y);
var newPosition = stage.getPointerPosition();
context.lineTo(newPosition.x, newPosition.y);
context.stroke();
debugger;
lastPointerPosition = newPosition;
context.strokeShape(this);
}
}
});
freeHandDrawingLayer.add(freeDraw);
// now we need to bind some events
// we need to start drawing on mousedown
// and stop drawing on mouseup
selectionBoxBackground.on('mousedown', function() {
if(isFreeDrawingMode){
isPaint = true;
lastPointerPosition = stage.getPointerPosition();
stage.draw();
}
});
selectionBoxBackground.on('mouseup', function() {
if(isFreeDrawingMode){
isPaint = false;
}
});
// and core function - drawing
selectionBoxBackground.on('mousemove', function() {
if (!isPaint) {
return;
}
freeHandDrawingLayer.draw();
});
}
在纯 JavaScript 中,这非常简单。
首先准备好你的画布和绘图上下文:
var context=document.getElementById("your_canvas_id").getContext("2d");
var image=document.getElementById("your_image_id");
现在您想将图像绘制到上下文中:
context.drawImage(image,0,0,image.width,image.height,0,0,image.width,image.height);
现在,当您想擦除部分图像时,只需在画布上绘制:
var x=y=radius=10;// Circle coordinates and radius.
context.fillStyle="#ffffff";// Your eraser color (not transparent)
context.beginPath();
context.arc(x,y,radius,0,Math.PI*2);
context.fill();
但是,这仅模拟擦除。如果您希望之后擦除的内容透明,您可能会查看context.clearRect
,但我不确定您将如何使用圆圈来做到这一点。