[英]Overcoming antialiasing on canvas lines for mouse event
我正面临一个显而易见的问题,即HTML画布中的行不能禁用抗锯齿(例如, 此问题提到只能针对使用context.imageSmoothingEnabled= false
图像执行此操作,而不能对行进行此操作)。
我想知道是否有任何更新,是否有可能画出清晰(即使“像素化”)的线条? 我所需要的就是例如使用普通的“铅笔”工具(请参见下面的左侧笔划)而不是更平滑的“画笔”类型(请参见右侧笔划)时MS Paint能够实现的功能。
这是一个问题,因为我试图设置一个鼠标事件以使行的颜色准确无误,但是在实际颜色周围使用了抗锯齿功能后,它会在光标到达中心部分之前返回一些不需要的颜色的线。
有人可以确认真的没有办法在画布上强迫“铅笔”状的笔触吗? 如果是这样,是否可能有一个简单的解决方法,例如“切除”笔触的边缘?
您可以使用SVG滤镜在画布上绘制这样的像素化形状,该滤镜会删除形状边缘的alpha值。 (但是SVG过滤器有点重。)
const ctx = canvas.getContext("2d"); //normal line(antialiased) ctx.moveTo(20,20); ctx.lineTo(180,20); ctx.stroke(); //set "crisp edge" filter ctx.filter = "url(#crisp)"; //crisp line ctx.beginPath();ctx.moveTo(20,40); ctx.lineTo(180,40); ctx.moveTo(20, 50); ctx.lineTo(180, 70); //crisp circle ctx.moveTo(150, 130); ctx.arc(100, 130, 50, 0, Math.PI*2); ctx.stroke();
<canvas id="canvas" width="200" height="200"></canvas> <svg style="visibility:hidden;width:0;height:0;"> <defs> <!--SVG filter to remove alpha--> <filter id="crisp"> <feComponentTransfer> <feFuncA type="discrete" tableValues="0,1"></feFuncA> </feComponentTransfer> </filter> </defs> </svg>
注意:但是Chrome通过使用SVG过滤器会在输出图像上引发安全错误。
如果您需要自己实现此类过滤器, ImageData
对象将为您提供帮助。 这没有安全错误风险。
但是手工制作的过滤器太重,无法应用于每个事件图纸。 您应该仔细考虑申请时间。
const ctx = canvas.getContext("2d"); //temporary canvas to removeAlpha const tmp = document.createElement("canvas"); [tmp.width, tmp.height] = [canvas.width, canvas.height]; const tctx = tmp.getContext("2d"); //normal line(antialiased) ctx.moveTo(20,20); ctx.lineTo(180,20); ctx.stroke(); //crisp line tctx.beginPath(); tctx.moveTo(20,40); tctx.lineTo(180,40); tctx.moveTo(20, 50); tctx.lineTo(180, 70); removeAlpha(); //crisp circle tctx.moveTo(150, 130); tctx.arc(100, 130, 50, 0, Math.PI*2); tctx.stroke(); removeAlpha(); //remove alpha on tmp canvas and draw it to main canvas. function removeAlpha(){ const threshold = 128;//you can change the value const id = tctx.getImageData(0, 0, tmp.width, tmp.height); const data = id.data;//pixel data array //remove alpha values pixel by pixel. for(let i = 0, len = canvas.width * canvas.height; i<len; i++){ const apos = i * 4 + 3;//alpha data position const a = data[apos]; data[apos] = a > threshold ? 255 : 0; } tctx.putImageData(id, 0, 0); ctx.drawImage(tmp, 0, 0); tctx.clearRect(0, 0, tmp.width, tmp.height); }
<canvas id="canvas" width="200" height="200"></canvas>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.