15

I'm using <canvas> to capture user input in the form of a signature and am trying to figure out how to smooth the input from the mouse.

I think I need to process the user's mouse movements chunk by chunk and smooth each chunk, I'm not after super smoothing but any improvement on the jagged input would be good.

Thanks, Mark

Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
dakine
  • 560
  • 2
  • 6
  • 19
  • 1
    Do you need a signature that is legal for, say, contractual purposes? If so, would a signature thus generated be sufficient? –  Sep 24 '10 at 17:03

6 Answers6

20

What you want is:

ctx.lineCap = 'round';

Here is an example of how it could be used:

Give it a try http://jsbin.com/ateho3

markup :

<canvas id="canvas"></canvas> 

JavaScript :

window.onload = function() {
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var width  = window.innerWidth;
    var height = window.innerHeight;
    canvas.height = height;
    canvas.width = width;
    canvas.addEventListener('mousedown', function(e) {
      this.down = true;  
      this.X = e.pageX ;
      this.Y = e.pageY ;
      this.color = rgb();
    }, 0);
    canvas.addEventListener('mouseup', function() {
      this.down = false;      
    }, 0);
    canvas.addEventListener('mousemove', function(e) {
      this.style.cursor = 'pointer';
      if(this.down) {
          ctx.beginPath();
          ctx.moveTo(this.X, this.Y);
          ctx.lineCap = 'round';
           ctx.lineWidth = 3;
          ctx.lineTo(e.pageX , e.pageY );
          ctx.strokeStyle = this.color;
          ctx.stroke();

         this.X = e.pageX ;
         this.Y = e.pageY ;
      }
    }, 0);

    function rgb() {
      color = 'rgb(';
      for(var i = 0; i< 3; i++) {
        color += Math.floor(Math.random() * 255)+',';
      }
      return color.replace(/\,$/,')');
    }    
  };
Trevor Clarke
  • 1,482
  • 1
  • 11
  • 20
9

I know that this is a 10 years old question but I think the answer is not complete. For a smooth line effect you need to set two properties to the canvas' context :

context.lineCap = 'round'
context.lineJoin = 'round'

The first one is for extremities of one path the second one is for corners of a path.

Some docs on lineJoin.
Some docs on lineCap.

Stephane L
  • 2,879
  • 1
  • 34
  • 44
5

I had to make a smooth canvas drawing for an mobile web application and learned couple of things. The Answer of Avinash is great but if you increase the line width, when you draw you will see broken lines. It is because the line cap is rectangular by default.

To make the line smoother you need to tweak something a bit.

ctx.lineCap = 'round';

this little tweak will give you a super smooth line.

To know more about this, try the following link

https://developer.mozilla.org/samples/canvas-tutorial/4_6_canvas_linecap.html

Community
  • 1
  • 1
Hasanavi
  • 8,455
  • 2
  • 29
  • 35
3

How about using Bezier curves?

Richard Ev
  • 52,939
  • 59
  • 191
  • 278
  • 1
    I modified Avinash's example to use `bezierCurveTo` instead of `lineTo`. The smoothing is more pronounced if you sample every other point. Even without smoothing my signature is not terribly "jagged". The parts of the signature with the least fidelity are the gross changes, which aren't really helped by smoothing. –  Sep 25 '10 at 00:32
  • 3
    Hi @unclebrad, did you post your modified example somewhere? We're facing the same problem. Thanks! – Crashalot Mar 27 '12 at 18:44
1

I haven't tested this in any way, but you could try drawing small circles with a radial fill gradient.

Castrohenge
  • 8,525
  • 5
  • 39
  • 66
0

Consider connecting dots by using lines automatically, or even, use quadraticCurveTo, but you must calculate the middle point by yourself.

Ming-Tang
  • 17,410
  • 8
  • 38
  • 76
  • Sample every few pixels and then draw a line sorta thing? rather than drawing every single dot that is recorded? – dakine Sep 24 '10 at 02:21
  • I have tried to use `quadraticCurveTo` and must say that it is a bit more complex than one may think. It may cause a presentation that looks like a seria of arcs if done just on each next segment while using control point calculated as half was the previous segment. In order to really do a smooth curve one needs to really recalc the whole path from the beginning to the end each new segment (or at least affect the prev segment with each new segment added) - FYI – GullerYA Feb 06 '21 at 17:23