How to create a soft stroke front using HTML5 canvas

I am creating a drawing application using an HTML5 canvas.

https://github.com/homanchou/sketchyPad

I can use rgba to control the opacity in my line strokes, but how can I achieve the soft feathers of my mouth brush against the hard circular edge?

+6
source share
4 answers

Three possible solutions:

  • You can write your lines in a screen canvas, apply a blur filter and then draw the result in a visible canvas.

  • If you use only straight line segments, you can use a linear gradient for each line segment. The direction of the gradient should be at a 90-degree angle compared to the direction of the line segment.

  • Draw the same lines several times in one place. First with full width and low alpha. Then reduce the width and increase the alpha.

An example of using a linear gradient for each line segment:

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

An example of drawing a line several times, decreasing the width and increasing the 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(); } 
+7
source

I am sure it depends on the browser you are using. The last thing I checked (some time ago, may have changed). Firefox and Chrome have no anti-alias boundaries, while IE9 does.

0
source

Once you have wrapped your lines on the canvas, you can soften (blur) using the CanvasPixelArray class. It is just a matter of adding color to neighboring pixels. Here is some good pixel manipulation info .

0
source

You can use the css filter to blur the canvas. This is possible with the SVG rasterization tag . Here's how you do it:

  • Make two canvases, one on top of the other. One of them allows to name "Target" and another "Buffer". The buffer is the one you draw onto, and Target is the result of the canvas.

  • Apply css-filter: blur(px) to the buffer canvas so that the user can instantly see the blurred preview.

  • This is the interesting part. At each stroke (i.e. mouseup), rasterize the buffer canvas, put the image in <svg><foreignObject></foreignObject></svg> , apply the same CSS filter to it, rasterize the SVG and place the rasterized SVG on the target canvas. Here's a gist with sample code .

0
source

Source: https://habr.com/ru/post/906898/


All Articles