我正致力于基于离子的应用。
我希望像用户这样的功能用手指填充图像(画布)上的红色。所以我已经完成了填充功能,但我想从画布中裁剪填充部分。我附上了一张图片供参考。
我想从上面的图像裁剪红色部分。我有谷歌搜索,但没有找到任何解决方案。
答案 0 :(得分:4)
如果要渲染选择区域(红色),那么解决方案很简单。
创建与图形大小相同的第二个画布,不要将其添加到DOM。将红色标记内容绘制到该画布上
显示画布上的图像首先渲染图像,然后渲染该标记 使用复合模式(如“叠加”)在图像上绘制画布,以便可以看到原始图像,并且标记的区域为红色。
现在你有两个图层,一个是图像,另一个是你可以用来获取标记内容副本的面具。
为此,创建第三个画布,将原始图像绘制到其上,然后将复合模式设置为“destination-in”。然后在上面画上面具。只保留标记的像素。
有关详细信息,请参阅示例
setTimeout(example,0); // ensures that the run us after parsing
function example(){
const ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
var cw = w / 2; // center
var ch = h / 2;
var selectLayer = CImageCtx(w,h); // creates a canvas
var selectedContent = CImageCtx(w,h); // the selected content
document.body.appendChild(selectedContent);
var image = new Image; // the image
image.src = " https://i.stack.imgur.com/QhFct.png";
// updates the masked result
function updateSelected(){
var ctx = selectedContent.ctx;
ctx.drawImage(image,0,0);
ctx.globalCompositeOperation = "destination-in";
ctx.drawImage(selectLayer,0,0);
ctx.globalCompositeOperation = "source-over";
}
function update(){
// if mouse down then
if(mouse.but){
// clear the mask if on the right image
if(mouse.oldBut === false && mouse.x > 256){
selectLayer.ctx.clearRect(0,0,w,h);
mouse.but = false;
}else{
// draw the red
selectLayer.ctx.fillStyle = "red";
fillCircle(mouse.x, mouse.y, 20, selectLayer.ctx);
}
// update the masked result
updateSelected();
}
// clear the canvas
ctx.clearRect(0,0,w,h);
// draw the image
ctx.drawImage(image,0,0);
// then draw the marking layer over it with comp overlay
ctx.globalCompositeOperation = "overlay";
ctx.drawImage(selectLayer,0,0);
ctx.globalCompositeOperation = "source-over";
mouse.oldBut = mouse.but;
requestAnimationFrame(update);
}
requestAnimationFrame(update);
}
//#############################################################################
// helper functions not part of the answer
//#############################################################################
const mouse = {
x : 0, y : 0, but : false,
events(e){
const m = mouse;
const bounds = canvas.getBoundingClientRect();
m.x = e.pageX - bounds.left - scrollX;
m.y = e.pageY - bounds.top - scrollY;
m.but = e.type === "mousedown" ? true : e.type === "mouseup" ? false : m.but;
}
};
(["down","up","move"]).forEach(name => document.addEventListener("mouse" + name,mouse.events));
const CImage = (w = 128, h = w) => (c = document.createElement("canvas"),c.width = w,c.height = h, c);
const CImageCtx = (w = 128, h = w) => (c = CImage(w,h), c.ctx = c.getContext("2d"), c);
const fillCircle = (l,y=ctx,r=ctx,c=ctx) =>{if(l.p1){c=y; r=leng(l);y=l.p1.y;l=l.p1.x }else if(l.x){c=r;r=y;y=l.y;l=l.x}c.beginPath(); c.arc(l,y,r,0,Math.PI*2); c.fill()}
body { font-family : arial; }
canvas { border : 2px solid black; }
Draw on image and the selected parts are shown on the right<br>
Click right image to reset selection<br>
<canvas id="canvas" width=256 height=256></canvas>
如果红色遮罩已经应用于图像,那么根据图像的红色程度,除了进行阈值滤镜之外,您可以做的事情并不多。但即使这样,你也会遇到较暗区域和已经含有红色区域的问题。
除非您拥有原始图像,否则效果会很差。
如果您有原始图像,则必须通过比较每个像素并仅选择不同的像素来访问图像数据并创建新图像作为蒙版。这将迫使您仅使用相同的域图像(或使用CORS交叉原始标题)