擦除 HTML5 Canvas 上的部分图像?
Erasing Parts of an Image on HTML5 Canvas?
我有一个 HTML5 Canvas。我正在使用 KineticJS(KonvaJS) canvas 库。在一片空白 canvas 上,我绘制了一个图像,如下图所示。现在我想创建一个圆形形状,可用于擦除部分图像。图中红圈就是橡皮擦
如何删除 HTML5 Canvas 上的部分图像?
简而言之JavaScript这很简单。
首先准备好 canvas 和绘图上下文:
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);
现在,当您想擦除部分图像时,只需在 canvas 上画画即可:
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
,但我不确定你如何用一个圆圈来做到这一点。
您可以对 "erase" 像素使用合成。
具体来说,您使用 destination-out
合成。
KineticJS 不支持合成,但您还有几个选择:
(注意:KineticJS已经变成了KonvaJS,我还没有检查KonvaJs是否支持合成。如果现在支持,就在KonvaJS中使用destination-out
合成)
选项#1:使用原生 canvas 元素作为您的 Kinetic.Image 来源
使用var c=document.createElement
,
在内存中创建html5canvas
将 canvas 调整为图像大小,
drawImage
你的图片放到 canvas,
创建一个 Kinetic.Image
并将其图像 属性 设置为对本机 canvas 的引用。 Kinetic.Image 将显示绘制到原生 canvas.
上的任何内容
var kImage=new Kinetic.Image({
...
image:c,
...
设置 canvas 合成,使新绘图成为 "erase" 现有像素:
c.globalCompositeOperation='destination-out';
监听圆圈橡皮擦上的拖动事件。使用这些事件在 canvas 上绘制一个圆圈,该圆圈的移动就像 Kinetic 圆圈橡皮擦的移动一样。由于 canvas 的合成设置为 "erase",因此在 canvas 上绘制的新圆将擦除 canvas 上的图像。
您的 Kinetic.Image 准确地反映了其 canvas 来源 (var c),因此您的 Kinetic.Image 也将显示正在擦除的图像以响应 Kinetic 圆圈橡皮擦运动。
选项 #2:使用 Kinetic.Shape
您可以通过在单独的图层上创建 Kinetic.Shape 并使用以下方法获取对本机 canvas 上下文的引用来执行与选项 #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();
});
}
我有一个 HTML5 Canvas。我正在使用 KineticJS(KonvaJS) canvas 库。在一片空白 canvas 上,我绘制了一个图像,如下图所示。现在我想创建一个圆形形状,可用于擦除部分图像。图中红圈就是橡皮擦
如何删除 HTML5 Canvas 上的部分图像?
简而言之JavaScript这很简单。
首先准备好 canvas 和绘图上下文:
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);
现在,当您想擦除部分图像时,只需在 canvas 上画画即可:
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
,但我不确定你如何用一个圆圈来做到这一点。
您可以对 "erase" 像素使用合成。
具体来说,您使用 destination-out
合成。
KineticJS 不支持合成,但您还有几个选择:
(注意:KineticJS已经变成了KonvaJS,我还没有检查KonvaJs是否支持合成。如果现在支持,就在KonvaJS中使用destination-out
合成)
选项#1:使用原生 canvas 元素作为您的 Kinetic.Image 来源
使用
var c=document.createElement
, 在内存中创建html5canvas
将 canvas 调整为图像大小,
drawImage
你的图片放到 canvas,创建一个
上的任何内容Kinetic.Image
并将其图像 属性 设置为对本机 canvas 的引用。 Kinetic.Image 将显示绘制到原生 canvas.var kImage=new Kinetic.Image({ ... image:c, ...
设置 canvas 合成,使新绘图成为 "erase" 现有像素:
c.globalCompositeOperation='destination-out';
监听圆圈橡皮擦上的拖动事件。使用这些事件在 canvas 上绘制一个圆圈,该圆圈的移动就像 Kinetic 圆圈橡皮擦的移动一样。由于 canvas 的合成设置为 "erase",因此在 canvas 上绘制的新圆将擦除 canvas 上的图像。
您的 Kinetic.Image 准确地反映了其 canvas 来源 (var c),因此您的 Kinetic.Image 也将显示正在擦除的图像以响应 Kinetic 圆圈橡皮擦运动。
选项 #2:使用 Kinetic.Shape
您可以通过在单独的图层上创建 Kinetic.Shape 并使用以下方法获取对本机 canvas 上下文的引用来执行与选项 #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();
});
}