如何使用HTML5画布创建柔和的笔触边缘

时间:2012-01-25 21:50:43

标签: jquery html5 canvas drawing

我正在使用HTML5画布创建绘图应用程序。

https://github.com/homanchou/sketchyPad

我可以使用rgba来控制笔划中的不透明度,但是如何获得柔软的羽毛画笔边缘与硬圆形边缘?

4 个答案:

答案 0 :(得分:7)

三种可能的解决方案:

  1. 您可以将线条写入离屏画布,应用模糊滤镜,然后将结果绘制到可见画布中。

  2. 如果您只使用直线段,则可以为每个线段使用线性渐变。与线段的方向相比,渐变的方向必须是90“角。

  3. 在同一个地方多次绘制相同的线条。首先是全宽和低alpha。然后减小宽度并增加alpha。

  4. 为每个线段使用线性渐变的示例:

    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(); }
    

答案 1 :(得分:0)

我很确定这取决于你正在使用的浏览器。最后我检查过(前一段时间 - 可能已经改变了)Firefox和Chrome没有抗锯齿边缘,而IE9确实如此。

答案 2 :(得分:0)

将线条提交到画布后,可以使用CanvasPixelArray类来柔化(模糊)。这只是将颜色添加到相邻像素的问题。 Here is a good info on pixel manipulation

答案 3 :(得分:0)

您可以使用css过滤器来模糊画布。可以使用SVG rasterization trick。这是你如何做到的:

  1. 制作两幅画布,一幅在另一幅画布之上。其中一个让我们打电话给«目标»和另一个«缓冲»。缓冲区是您绘制的缓冲区,而Target是生成的画布。

  2. css-filter: blur(px)应用于缓冲画布,以便用户可以立即看到模糊的预览。

  3. 这是有趣的部分。在每个笔划上(即在鼠标上),栅格化缓冲区画布,将图像放入<svg><foreignObject></foreignObject></svg>,对其应用相同的CSS滤镜,栅格化SVG,并将栅格化的SVG放在目标画布上。这是gist with code example