yajnab
yajnab

Reputation: 41

Draw a straight line between two points selected in a mouse down event

I have code which draws a line as I move my mouse while clicking the mouse (mousedown event and mousemove event).

I also want a straight line to be drawn from the beginning of the point (where I first clicked the point, mousedown event) to the end (where I lift the mouse event, mouseup event).

(function() {
      var canvas = document.querySelector('#paint');
      var ctx = canvas.getContext('2d');

      var sketch = document.querySelector('#sketch');
      var sketch_style = getComputedStyle(sketch);
      canvas.width = parseInt(sketch_style.getPropertyValue('width'));
      canvas.height = parseInt(sketch_style.getPropertyValue('height'));

      var mouse = {
        x: 0,
        y: 0
      };
      
      var last_mouse = {
        x: 0,
        y: 0
      };

      /* Mouse Capturing Work */
      canvas.addEventListener('mousemove', function(e) {
        last_mouse.x = mouse.x;
        last_mouse.y = mouse.y;

        mouse.x = e.pageX - this.offsetLeft;
        mouse.y = e.pageY - this.offsetTop;
      }, false);


      /* Drawing on Paint App */
      ctx.lineWidth = 5;
      ctx.lineJoin = 'round';
      ctx.lineCap = 'round';
      ctx.strokeStyle = 'black';

      canvas.addEventListener('mousedown', function(e) {
        canvas.addEventListener('mousemove', onPaint, false);
      }, false);

      canvas.addEventListener('mouseup', function() {
        canvas.removeEventListener('mousemove', onPaint, false);
      }, false);

      var onPaint = function() {
        ctx.beginPath();
        ctx.moveTo(last_mouse.x, last_mouse.y);
        ctx.lineTo(mouse.x, mouse.y);
        ctx.closePath();
        ctx.stroke();
      };
    }());
#sketch{
  width: 100%;
  height: 200px;
  background-color: #CCCCCC;
}
<div id="sketch">
  <canvas id="paint">
  </canvas>
</div>

Upvotes: 1

Views: 1746

Answers (2)

Blindman67
Blindman67

Reputation: 54026

Just add another position object eg

  const mouseDownAt = {x: 0, y: 0};

Then when the mouse down event happens record that position

  canvas.addEventListener('mousedown', function(e) {

    mouseDownAt.x = e.pageX - this.offsetLeft;
    mouseDownAt.y = e.pageY - this.offsetTop;

    canvas.addEventListener('mousemove', onPaint, false);
  }, false);

On the mouse up event draw the closing line

  canvas.addEventListener('mouseup', function() {
    lastMouse.x = mouse.x;
    lastMouse.y = mouse.y;
    mouse.x = e.pageX - this.offsetLeft;
    mouse.y = e.pageY - this.offsetTop;

    // if mouse has moved?? draw the last little bit
    if (mouse.x !== last_mouse.x || mouse.y !== last_mouse.y) {
         onPaint();
    }

    // set the end position
    lastMouse.x = mouse.x;
    lastMouse.y = mouse.y;

    // use the mouse down at pos as the new position
    mouse.x = mouseDownAt.x;
    mouse.y = mouseDownAt.y;

    // draw the line
    onPaint();

    canvas.removeEventListener('mousemove', onPaint, false);
  }, false);

BTW I am not sure if you know that using closePath as you do will render the path segment twice and will reduce the quality of the line (too strong alphas on the anti aliasing) . closePath is like lineTo (draws a line segment) and not related to ctx.beginPath

  function onPaint () {
    ctx.beginPath();
    ctx.lineTo(lastMouse.x, lastMouse.y);  // after beginPath lineTo is the same
                                             // moveTo
    ctx.lineTo(mouse.x, mouse.y);
    ctx.stroke();
  };

Upvotes: 1

Julian
Julian

Reputation: 1297

You want to store the coordinates of the mouseDown event and then use them to draw a single line to the coordinates of the mouseUp event. I modified your code to show a way that can be done:

(function() {
      var canvas = document.querySelector('#paint');
      var ctx = canvas.getContext('2d');

      var sketch = document.querySelector('#sketch');
      var sketch_style = getComputedStyle(sketch);
      canvas.width = parseInt(sketch_style.getPropertyValue('width'));
      canvas.height = parseInt(sketch_style.getPropertyValue('height'));

      var mouse = {
        x: 0,
        y: 0
      };
      
      var last_mouse = {
        x: 0,
        y: 0
      };

      /* Mouse Capturing Work */
      canvas.addEventListener('mousemove', function(e) {
        last_mouse.x = mouse.x;
        last_mouse.y = mouse.y;

        mouse.x = e.pageX - this.offsetLeft;
        mouse.y = e.pageY - this.offsetTop;
      }, false);


      /* Drawing on Paint App */
      ctx.lineWidth = 5;
      ctx.lineJoin = 'round';
      ctx.lineCap = 'round';
      ctx.strokeStyle = 'black';
      canvas.addEventListener('mousedown', function(e) {
        initialPoint = {x:mouse.x, y:mouse.y}
        canvas.addEventListener('mousemove', onPaint, false);
      }, false);

      canvas.addEventListener('mouseup', function() {
        drawStraightLine()
        canvas.removeEventListener('mousemove', onPaint, false);
      }, false);

      var onPaint = function() {
        ctx.beginPath();
        ctx.moveTo(last_mouse.x, last_mouse.y);
        ctx.lineTo(mouse.x, mouse.y);
        ctx.strokeStyle = "#000000";
        ctx.closePath();
        ctx.stroke();
      };
      
      let initialPoint
      const drawStraightLine = function() {
        ctx.beginPath();
        ctx.moveTo(initialPoint.x, initialPoint.y);
        ctx.lineTo(mouse.x, mouse.y);
        ctx.strokeStyle = "#FF000077";
        ctx.stroke();
      }
    }());
#sketch{
  width: 100%;
  height: 180px;
  background-color: #DDDDDD;
}
<div id="sketch">
  <canvas id="paint" />
</div>

initialPoint is the mouse position when the button is pressed and drawStarightLine() is the method executed when said button is released. Also added different colors to the lines to make it obvious.

Upvotes: 5

Related Questions