Smooth jagged lines drawn by user in HTML5 canvas

2019-04-28 12:22发布

问题:

We have an HTML5 drawing app where users can draw lines using a pencil tool.

Compared to Flash-based drawing apps, the lines have slightly jagged edges and appear somewhat blurry. This happens because users need to keep the line perfectly straight while drawing, or the algorithm senses every pixel deviation and projects it as a jagged edge.

Drawing smooth, sharp circles is impossible as a result.

Somehow, other drawing apps are able to smooth out these jagged edges while letting users draw lines (straight or not).

Is there a way we can smooth out these lines?

Demo (choose the pencil tool): http://devfiles.myopera.com/articles/649/example5.html

Our app uses similar code.

回答1:

Here's an example of a quick way using quadratic curves and 'round' lineJoin:

http://jsfiddle.net/NWBV4/10/



回答2:

As for lines or vectors .. this post is what you want

Drawing GOOD LOOKING (like in Flash) lines on canvas (HTML5) - possible?

TL;DR use SVG

where ctx is context

ctx.lineCap = "round"

then for the drawing

ctx.beginPath();
ctx.moveTo(data.line.startX,data.line.startY);
ctx.lineTo(data.line.endX, data.line.endY);
ctx.strokeStyle = data.line.color;
ctx.stroke();

proof

http://gentle-leaf-5790.herokuapp.com/



回答3:

You might want to enforce a minimum length on the line that is drawn. To do this, take the pencil section of that example code and change it to something like this:

  tools.pencil = function () {
    var tool = this;
    // variables for last x, y and min_length of line
    var lx; 
    var ly; 
    var min_length = 3;
    this.started = false;

    // This is called when you start holding down the mouse button.
    // This starts the pencil drawing.
    this.mousedown = function (ev) {
        context.beginPath();
        context.moveTo(ev._x, ev._y);
        tool.started = true;
        // update last x,y coordinates
        lx = ev._x;
        ly = ev._y;
    };

    // This function is called every time you move the mouse. Obviously, it only 
    // draws if the tool.started state is set to true (when you are holding down 
    // the mouse button).
    this.mousemove = function (ev) {

      if (tool.started && (Math.sqrt(Math.pow(lx - ev._x, 2) + Math.pow(ly - ev._y, 2)) > min_length)) {
        context.lineTo(ev._x, ev._y);
        context.stroke();
        lx = ev._x;
        ly = ev._y;
      }
    };

    // This is called when you release the mouse button.
    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
        img_update();
      }
    };
  };