如何使用HTML5canvas创建柔和的笔触边缘
我正在使用HTML5canvas创建绘图应用程序。
https://github.com/homanchou/sketchyPad
我可以使用rgba来控制笔划中的不透明度,但是如何获得柔软的羽毛画笔边缘与硬圆形边缘?
三种可能的解决方
-
您可以将线条写入离屏canvas,应用模糊滤镜,然后将结果绘制到可见canvas中。
-
如果仅使用直线段,则可以为每个线段使用线性渐变。 与线段的方向相比,梯度的方向必须是90“角。
-
在同一个地方多次绘制相同的线条。 首先是全宽和低alpha。 然后减小宽度并增加alpha。
每个线段使用线性渐变的示例:
http://jsfiddle.net/chdh/MmYAt/
function drawSoftLine(x1, y1, x2, y2, lineWidth, r, g, b, a) { var lx = x2 - x1; var ly = y2 - y1; var lineLength = Math.sqrt(lx*lx + ly*ly); var wy = lx / lineLength * lineWidth; var wx = ly / lineLength * lineWidth; var gradient = ctx.createLinearGradient(x1-wx/2, y1+wy/2, x1+wx/2, y1-wy/2); // The gradient must be defined accross the line, 90° turned compared // to the line direction. gradient.addColorStop(0, "rgba("+r+","+g+","+b+",0)"); gradient.addColorStop(0.43, "rgba("+r+","+g+","+b+","+a+")"); gradient.addColorStop(0.57, "rgba("+r+","+g+","+b+","+a+")"); gradient.addColorStop(1, "rgba("+r+","+g+","+b+",0)"); ctx.save(); ctx.beginPath(); ctx.lineWidth = lineWidth; ctx.strokeStyle = gradient; ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); ctx.restore(); }
通过减小宽度和增加alpha来多次绘制线条的示例:
http://jsfiddle.net/chdh/RmtxL/
function drawSoftLine(x1, y1, x2, y2, lineWidth, r, g, b, a) { ctx.save(); var widths = [1 , 0.8 , 0.6 , 0.4 , 0.2 ]; var alphas = [0.2 , 0.4 , 0.6 , 0.8 , 1 ]; var previousAlpha = 0; for (var pass = 0; pass < widths.length; pass++) { ctx.beginPath(); ctx.lineWidth = lineWidth * widths[pass]; var alpha = a * alphas[pass]; // Formula: (1 - alpha) = (1 - deltaAlpha) * (1 - previousAlpha) var deltaAlpha = 1 - (1 - alpha) / (1 - previousAlpha) ctx.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + deltaAlpha + ")"; ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); previousAlpha = alpha; } ctx.restore(); }
我很确定这取决于你正在使用的浏览器。 最后我检查了(前一段时间 – 可能已经改变了)Firefox和Chrome不会反边缘,而IE9会这样做。
将线条提交到canvas后,可以使用CanvasPixelArray类来柔化(模糊)。 这只是将您的颜色添加到相邻像素的问题。 这是关于像素操作的一个很好的信息 。
您可以使用cssfilter来模糊canvas。 有可能使用SVG光栅化技巧 。 这是你如何做到的:
-
制作两幅canvas,一幅在另一幅canvas之上。 其中一个让我们称之为«目标»和另一个«缓冲»。 缓冲区是您绘制的缓冲区,而Target是生成的canvas。
-
将
css-filter: blur(px)
应用于Buffercanvas,以便用户可以立即看到模糊的预览。 -
这是有趣的部分。 在每个笔划(即鼠标上),栅格化缓冲区canvas,将图像放入
,对其应用相同的CSS滤镜,栅格化SVG,并将栅格化的SVG置于其上目标canvas。 这是代码示例的要点 。