1

I have a canvas on which user can draw point on click on any part of it. As one know we must give the user the possibility to undo an action that he as done. This is where I'am stuck, how can I program the codes to allow the user to remove the point on double click on the the point he wants to remove ?

<canvas id="canvas" width="160" height="160" style="cursor:crosshair;"></canvas>

1- Codes to draw the canvas and load an image in it

var canvasOjo1 = document.getElementById('canvas'),
context1 = canvasOjo1.getContext('2d');
ojo1();

function ojo1()
{

base_image1 = new Image();
base_image1.src = 'https://www.admedicall.com.do/admedicall_v1//assets/img/patients-pictures/620236447.jpg';
base_image1.onload = function(){
context1.drawImage(base_image1, 0, 0);
}
}

2- Codes to draw the points

$("#canvas").click(function(e){
getPosition(e); 
});

var pointSize = 3;

function getPosition(event){
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;

drawCoordinates(x,y);
}

function drawCoordinates(x,y){  
var ctx = document.getElementById("canvas").getContext("2d");


ctx.fillStyle = "#ff2626"; // Red color

ctx.beginPath();
ctx.arc(x, y, pointSize, 0, Math.PI * 2, true);
ctx.fill();
}

My fiddle :http://jsfiddle.net/xpvt214o/834918/

By hover the mouse over the image we see a cross to create the point.

How can i remove a point if i want to after create it on double click ?

Thank you in advance.

Diasline
  • 625
  • 3
  • 32
  • You will have to store every point in an array somewhere and then render youir canvas based on that array when it changes. When they doubleclick, match the point with the one in the array and splice it out of it. Now redraw the whole canvas using the array that now is one item shorter. It wont be possible with the fixed-draw canvas you have right now. – somethinghere Sep 19 '18 at 14:48
  • Possible duplicate of [Undo and Redo Canvas Not Working as Expected](https://stackoverflow.com/questions/48950027/undo-and-redo-canvas-not-working-as-expected) – Helder Sepulveda Sep 19 '18 at 15:02

1 Answers1

1

Please read first this answer how to differentiate single click event and double click event because this is a tricky thing.

For the sake of clarity I've simplified your code by removing irrelevant things.

Also please read the comments of my code.

let pointSize = 3;
var points = [];
var timeout = 300;
var clicks = 0;

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let cw = (canvas.width = 160);
let ch = (canvas.height = 160);

function getPosition(event) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top
  };
}

function drawCoordinates(point, r) {
  ctx.fillStyle = "#ff2626"; // Red color
  ctx.beginPath();
  ctx.arc(point.x, point.y, r, 0, Math.PI * 2, true);
  ctx.fill();
}

canvas.addEventListener("click", function(e) {
  clicks++;
  var m = getPosition(e);
  // this point won't be added to the points array
  // it's here only to mark the point on click since otherwise it will appear with a delay equal to the timeout
  drawCoordinates(m, pointSize);
  
  if (clicks == 1) {
    setTimeout(function() {
      if (clicks == 1) {
        // on click add a new point to the points array
        points.push(m);
      } else { // on double click 
        // 1. check if point in path
        for (let i = 0; i < points.length; i++) {
          ctx.beginPath();
          ctx.arc(points[i].x, points[i].y, pointSize, 0, Math.PI * 2, true);

          if (ctx.isPointInPath(m.x, m.y)) {
            points.splice(i, 1); // remove the point from the array
            break;// if a point is found and removed, break the loop. No need to check any further.
          }
        }

        //clear the canvas
        ctx.clearRect(0, 0, cw, ch);
      }

      points.map(p => {
        drawCoordinates(p, pointSize);
      });
      clicks = 0;
    }, timeout);
  }
});
body {
  background: #20262E;
  padding: 20px;
}
<canvas id="canvas" style="cursor:crosshair;border:1px solid white"></canvas>
enxaneta
  • 31,608
  • 5
  • 29
  • 42
  • Hoo man i do not know how to thank for your codes, thank you so much , it is exactly what I nedd. ): – Diasline Sep 20 '18 at 13:17
  • Even if you remove the image out of the canvas I will put it again because, the image is very important. Thanks again – Diasline Sep 20 '18 at 13:19
  • 1
    I draw the image onto the canvas, as a result when I double click to remove a point a part of the canvas is removed but not only the point how can I fix this ? I updated my fiddle to see what i mean. – Diasline Sep 21 '18 at 15:06
  • In this case you need to redraw the image. In my code you need to add `ctx.drawImage(base_image1, 0, 0);` just before `points.map(p => { drawCoordinates(p, pointSize); });` If this is not solving your problem please consider to ask an other question. I'll be glad to help. – enxaneta Sep 21 '18 at 15:14
  • let me try and I let you know – Diasline Sep 21 '18 at 15:19