I have this discussion which indicates how to make a pencil tool.
How can I detect whether the mouse is hovering on drawn area/points/images using the pencil tool? T
You can get the (per pixel) image data from a canvas: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData. Then check if the mouse is hovering over a green pixel.
Here's a quick demo. Move your mouse within 5px of either end of the line to see the guides.
The idea is that it uses collision detection to work out if the mouse is within 5 pixels of the start or end of the line.
You can easily change from ugly square guides to a circle. You can essentially do what you want.
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 400;
document.body.appendChild(canvas);
//add as many lines as you want
var lines = [
{start: {x: 100, y: 100}, end: {x: 200, y: 300}},
{start: {x: 200, y: 150}, end: {x: 50, y: 250}},
{start: {x: 240, y: 240}, end: {x: 450, y: 150}},
{start: {x: 160, y: 340}, end: {x: 10, y: 90}},
{start: {x: 380, y: 270}, end: {x: 300, y: 380}}
];
function render(){
ctx.clearRect(0,0,500,400);
for(var c = 0; c < lines.length; c++){
ctx.moveTo(lines[c].start.x, lines[c].start.y);
ctx.lineTo(lines[c].end.x, lines[c].end.y);
ctx.stroke();
}
}
render();
var mouse = {x: 0, y: 0};
document.addEventListener('mousemove', function(e){
mouse.x = e.clientX;
mouse.y = e.clientY;
render();
for(var c = 0; c < lines.length; c++){
if(
//check if within 10px of start of line
(mouse.x > lines[c].start.x - 5 &&
mouse.x < lines[c].start.x + 5 &&
mouse.y > lines[c].start.y - 5 &&
mouse.y < lines[c].start.y + 5) ||
//same for the end of the line
(mouse.x > lines[c].end.x - 5 &&
mouse.x < lines[c].end.x + 5 &&
mouse.y > lines[c].end.y - 5 &&
mouse.y < lines[c].end.y + 5)
){
showGuides(c);
}
}
});
//function to show the guides
function showGuides(i){
ctx.fillRect(lines[i].start.x - 5, lines[i].start.y - 5, 10, 10);
ctx.fillRect(lines[i].end.x - 5, lines[i].end.y - 5, 10, 10);
}
body{
margin: 0;
}
^ ^ ^
| | |
Run code snippet
The only solution in your case is to save all drawn points into arrays, themselves saved in one array containing all your pathes :
onmousedown
: create a new path array.onmousemove
:var ctx = canvas.getContext("2d"),
painting = false,
lineThickness = 1;
canvas.width = canvas.height = 600;
var dCanvas = canvas.cloneNode(true);
dCtx = dCanvas.getContext('2d');
pCanvas = canvas.cloneNode(true);
pCtx = pCanvas.getContext('2d');
dCtx.fillStyle = "#FFF";
pCtx.fillStyle = "red";
ctx.fillRect(0, 0, 600, 600);
var pathes = [],
currentPath;
canvas.onmousedown = function(e) {
currentPath = [];
pathes.push(currentPath);
painting = true;
};
canvas.onmouseup = function(e) {
painting = false;
}
canvas.onmousemove = function(e) {
pCtx.clearRect(0, 0, canvas.width, canvas.height);
var mouseX = e.pageX - this.offsetLeft,
mouseY = e.pageY - this.offsetTop;
if (painting) {
var lastPoint = currentPath[currentPath.length-1] || {
x: e.pageX - canvas.offsetLeft,
y: e.pageY - canvas.offsetTop
};
var x1 = mouseX,
x2 = lastPoint.x,
y1 = mouseY,
y2 = lastPoint.y;
var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
if (steep) {
var x = x1;
x1 = y1;
y1 = x;
var y = y2;
y2 = x2;
x2 = y;
}
if (x1 > x2) {
var x = x1;
x1 = x2;
x2 = x;
var y = y1;
y1 = y2;
y2 = y;
}
var dx = x2 - x1,
dy = Math.abs(y2 - y1),
error = 0,
de = dy / dx,
yStep = -1,
y = y1;
if (y1 < y2) {
yStep = 1;
}
lineThickness = 5-Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) / 10;
if (lineThickness < 1) {
lineThickness = 1;
}
for (var x = x1; x < x2; x++) {
if (steep) {
dCtx.fillRect(y, x, lineThickness, lineThickness);
currentPath.push({x: y,y: x});
} else {
dCtx.fillRect(x, y, lineThickness, lineThickness);
currentPath.push({x: x,y: y});
}
error += de;
if (error >= 0.5) {
y += yStep;
error -= 1.0;
}
}
currentPath.push({x: mouseX,y: mouseY});
} else {
pathes.forEach(function(path) {
if (path.some(function(point) {
return isBetween(mouseX, point.x, 5) && isBetween(mouseY, point.y, 5)
})) {
pCtx.beginPath();
pCtx.arc(path[0].x+2.5, path[0].y+2.5, 5, 0, Math.PI*2);
pCtx.fill();
pCtx.beginPath();
pCtx.arc(path[path.length-1].x+2.5, path[path.length-1].y+2.5, 5, 0, Math.PI*2);
pCtx.fill();
}
});
}
ctx.fillRect(0, 0, 600, 600);
ctx.drawImage(dCanvas, 0, 0);
ctx.drawImage(pCanvas, 0, 0);
}
function isBetween(x, y, z) {
return (x >= y - z && x <= y + z);
}
canvas {
border: 1px solid
}
<canvas id="canvas" width="500" height="500"></canvas>