Editing Selections of Path Points or line












1















I'm trying to find a way to drag and drop polygon point or line with javascript in html5 canvas by selecting a path points with mouse click on it



Kind like image below
enter image description here



the selected points are moved by clicking and dragging them into new position






var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = ;
var isDone=false;

$('#done').click(function(){
isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}

function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>












share|improve this question























  • So, what is your question exactly? Are you asking us to write code that will allow for path editing drag and drop?

    – Dvorog
    Nov 22 '18 at 10:06













  • The question is in the first line : how to drag and drop polygon point. The problem of a drag and drop for polygon point is the position change of the two line that made that point. I'm asking for any help to figured out how to this : explanation, code, link anything

    – sonia maklouf
    Nov 22 '18 at 10:22
















1















I'm trying to find a way to drag and drop polygon point or line with javascript in html5 canvas by selecting a path points with mouse click on it



Kind like image below
enter image description here



the selected points are moved by clicking and dragging them into new position






var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = ;
var isDone=false;

$('#done').click(function(){
isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}

function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>












share|improve this question























  • So, what is your question exactly? Are you asking us to write code that will allow for path editing drag and drop?

    – Dvorog
    Nov 22 '18 at 10:06













  • The question is in the first line : how to drag and drop polygon point. The problem of a drag and drop for polygon point is the position change of the two line that made that point. I'm asking for any help to figured out how to this : explanation, code, link anything

    – sonia maklouf
    Nov 22 '18 at 10:22














1












1








1








I'm trying to find a way to drag and drop polygon point or line with javascript in html5 canvas by selecting a path points with mouse click on it



Kind like image below
enter image description here



the selected points are moved by clicking and dragging them into new position






var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = ;
var isDone=false;

$('#done').click(function(){
isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}

function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>












share|improve this question














I'm trying to find a way to drag and drop polygon point or line with javascript in html5 canvas by selecting a path points with mouse click on it



Kind like image below
enter image description here



the selected points are moved by clicking and dragging them into new position






var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = ;
var isDone=false;

$('#done').click(function(){
isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}

function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>








var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = ;
var isDone=false;

$('#done').click(function(){
isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}

function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>





var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = ;
var isDone=false;

$('#done').click(function(){
isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}

function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}

body{ background-color: ivory; }
#canvas{border:1px solid red;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Click to assign polygon vertices</h4>
<button id=done>Click when done assigning points</button>
<br><canvas id="canvas" width=300 height=300></canvas>






javascript html5-canvas






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 22 '18 at 9:30









sonia makloufsonia maklouf

6152619




6152619













  • So, what is your question exactly? Are you asking us to write code that will allow for path editing drag and drop?

    – Dvorog
    Nov 22 '18 at 10:06













  • The question is in the first line : how to drag and drop polygon point. The problem of a drag and drop for polygon point is the position change of the two line that made that point. I'm asking for any help to figured out how to this : explanation, code, link anything

    – sonia maklouf
    Nov 22 '18 at 10:22



















  • So, what is your question exactly? Are you asking us to write code that will allow for path editing drag and drop?

    – Dvorog
    Nov 22 '18 at 10:06













  • The question is in the first line : how to drag and drop polygon point. The problem of a drag and drop for polygon point is the position change of the two line that made that point. I'm asking for any help to figured out how to this : explanation, code, link anything

    – sonia maklouf
    Nov 22 '18 at 10:22

















So, what is your question exactly? Are you asking us to write code that will allow for path editing drag and drop?

– Dvorog
Nov 22 '18 at 10:06







So, what is your question exactly? Are you asking us to write code that will allow for path editing drag and drop?

– Dvorog
Nov 22 '18 at 10:06















The question is in the first line : how to drag and drop polygon point. The problem of a drag and drop for polygon point is the position change of the two line that made that point. I'm asking for any help to figured out how to this : explanation, code, link anything

– sonia maklouf
Nov 22 '18 at 10:22





The question is in the first line : how to drag and drop polygon point. The problem of a drag and drop for polygon point is the position change of the two line that made that point. I'm asking for any help to figured out how to this : explanation, code, link anything

– sonia maklouf
Nov 22 '18 at 10:22












2 Answers
2






active

oldest

votes


















2














The answer given is an example of bad practice in regard to handling the mouse and rendering content.



Rendering from mouse events will chew power and force canvas renders when not needed. The mouse can fire at rates up to 1000 times a second while the max display rate is only 60 times a second.



Using mouse move events means that many of the rendered updates will not be seen by the user, and are just wasted CPU/GPU cycles at best, at worst a major battery drain.



Always use requestAnimationFrame to render any content that is frequently changing.



The example below decoples the rendering from input events using requestAnimationFrame to render content only when needed. It also adds some feedback for the user via the cursor and highlighting points.






var ctx = canvas.getContext("2d");
requestAnimationFrame(update)

mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
function mouseEvents(e){
const bounds = canvas.getBoundingClientRect();
mouse.x = e.pageX - bounds.left - scrollX;
mouse.y = e.pageY - bounds.top - scrollY;
mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
mouse.update = true;
}
["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



ctx.lineWidth = 2;
ctx.strokeStyle = "blue";
const point = (x,y) => ({x,y});
const poly = () => ({
points : ,
addPoint(p){ this.points.push(point(p.x,p.y)) },
draw() {
ctx.lineWidth = 2;
ctx.strokeStyle = "blue";
ctx.beginPath();
for (const p of this.points) { ctx.lineTo(p.x,p.y) }
ctx.closePath();
for (const p of this.points) {
ctx.moveTo(p.x + 4,p.y);
ctx.arc(p.x,p.y,4,0,Math.PI *2);
}
ctx.stroke();
},
closest(pos, dist = 8) {
var i = 0, index = -1;
dist *= dist;
for (const p of this.points) {
var x = pos.x - p.x;
var y = pos.y - p.y;
var d2 = x * x + y * y;
if (d2 < dist) {
dist = d2;
index = i;
}
i++;
}
if (index > -1) { return this.points[index] }
}
});
function drawCircle(pos,color="red",size=8){
ctx.strokeStyle = color;
ctx.beginPath();
ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
ctx.stroke();
}
const polygon = poly();
var activePoint,cursor;
var dragging= false;
function update(){
if (mouse.update) {
cursor = "crosshair";
ctx.clearRect(0,0,canvas.width,canvas.height);
if (!dragging) { activePoint = polygon.closest(mouse) }
if (activePoint === undefined && mouse.button) {
polygon.addPoint(mouse);
mouse.button = false;
} else if(activePoint) {
if (mouse.button) {
if(dragging) {
activePoint.x += mouse.x - mouse.lx;
activePoint.y += mouse.y - mouse.ly;
} else { dragging = true }
} else { dragging = false }
}
polygon.draw();
if (activePoint) {
drawCircle(activePoint);
cursor = "move";
}

mouse.lx = mouse.x;
mouse.ly = mouse.y;
canvas.style.cursor = cursor;
mouse.update = false;
}
requestAnimationFrame(update)
}

#canvas{
border:1px
solid black;
}

<canvas id="canvas" width=300 height=300></canvas>








share|improve this answer































    2














    I've made a few changes to your code. Since I need to detect the position of the mouse I've added a function to do this.



    The logic is as it follows:




    1. you draw the points.


    2. When you are done you can begin to drag the points


    3. If you click inside a point (a small circle around the point) you save the index of the point.


    4. on mouse move you move the point you clicked in.


    5. on mouse up no point is dragged anymore.



    I hope this is what you need.






    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var cw = canvas.width;
    var ch = canvas.height;
    var mouse = {};
    var draggable = false;

    context.lineWidth = 2;
    context.strokeStyle = "blue";

    var coordinates = ;
    var isDone = false;

    done.addEventListener("click", function() {
    isDone = true;
    });

    canvas.addEventListener("mousedown", function(e) {
    handleMouseDown(e);
    });

    function handleMouseDown(e) {
    mouse = oMousePos(canvas, e);
    //if isDone you can drag
    if (isDone || coordinates.length > 10) {
    for (index = 0; index < coordinates.length; index++) {
    // you draw a small circle no stroke, no fill
    context.beginPath();
    context.arc(
    coordinates[index].x,
    coordinates[index].y,
    5,
    0,
    2 * Math.PI
    );
    // if the mouse is inside the circle
    if (context.isPointInPath(mouse.x, mouse.y)) {
    // you can drag this point
    // I'm using index + 1 because index == 0 is false
    draggable = index + 1;
    // if I have a point a can break the loop
    break;
    }
    }
    } else {
    coordinates.push({ x: mouse.x, y: mouse.y });
    drawPolygon();
    }
    }

    function drawPolygon() {
    context.clearRect(0, 0, cw, ch);
    context.beginPath();
    context.moveTo(coordinates[0].x, coordinates[0].y);
    for (index = 1; index < coordinates.length; index++) {
    context.lineTo(coordinates[index].x, coordinates[index].y);
    }
    context.closePath();
    context.stroke();
    // Additionaly I'm drawing a small circle around every point
    // you can delete this.
    for (index = 0; index < coordinates.length; index++) {
    context.beginPath();
    context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
    context.stroke();
    }
    }

    canvas.addEventListener("mousemove", function(e) {
    if (isDone) {
    if (draggable) {
    mouse = oMousePos(canvas, e);
    // draggable - 1 is the index of the point in the coordinates array
    coordinates[draggable - 1].x = mouse.x;
    coordinates[draggable - 1].y = mouse.y;
    drawPolygon();
    }
    }
    });

    canvas.addEventListener("mouseup", function(e) {
    if (draggable) {
    draggable = false;
    }
    });


    // a function to detect the mouse position

    function oMousePos(canvas, evt) {
    var ClientRect = canvas.getBoundingClientRect();
    return {
    //objeto
    x: Math.round(evt.clientX - ClientRect.left),
    y: Math.round(evt.clientY - ClientRect.top)
    };
    }

    body{ background-color: ivory; }
    #canvas{border:1px solid red;}

    <h4>Click to assign polygon vertices</h4>
    <button id=done>Click when done assigning points</button>
    <br><canvas id="canvas" width=300 height=300></canvas>








    share|improve this answer
























    • Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

      – sonia maklouf
      Nov 22 '18 at 15:10











    • coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

      – enxaneta
      Nov 22 '18 at 18:18











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427699%2fediting-selections-of-path-points-or-line%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    The answer given is an example of bad practice in regard to handling the mouse and rendering content.



    Rendering from mouse events will chew power and force canvas renders when not needed. The mouse can fire at rates up to 1000 times a second while the max display rate is only 60 times a second.



    Using mouse move events means that many of the rendered updates will not be seen by the user, and are just wasted CPU/GPU cycles at best, at worst a major battery drain.



    Always use requestAnimationFrame to render any content that is frequently changing.



    The example below decoples the rendering from input events using requestAnimationFrame to render content only when needed. It also adds some feedback for the user via the cursor and highlighting points.






    var ctx = canvas.getContext("2d");
    requestAnimationFrame(update)

    mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
    function mouseEvents(e){
    const bounds = canvas.getBoundingClientRect();
    mouse.x = e.pageX - bounds.left - scrollX;
    mouse.y = e.pageY - bounds.top - scrollY;
    mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
    mouse.update = true;
    }
    ["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



    ctx.lineWidth = 2;
    ctx.strokeStyle = "blue";
    const point = (x,y) => ({x,y});
    const poly = () => ({
    points : ,
    addPoint(p){ this.points.push(point(p.x,p.y)) },
    draw() {
    ctx.lineWidth = 2;
    ctx.strokeStyle = "blue";
    ctx.beginPath();
    for (const p of this.points) { ctx.lineTo(p.x,p.y) }
    ctx.closePath();
    for (const p of this.points) {
    ctx.moveTo(p.x + 4,p.y);
    ctx.arc(p.x,p.y,4,0,Math.PI *2);
    }
    ctx.stroke();
    },
    closest(pos, dist = 8) {
    var i = 0, index = -1;
    dist *= dist;
    for (const p of this.points) {
    var x = pos.x - p.x;
    var y = pos.y - p.y;
    var d2 = x * x + y * y;
    if (d2 < dist) {
    dist = d2;
    index = i;
    }
    i++;
    }
    if (index > -1) { return this.points[index] }
    }
    });
    function drawCircle(pos,color="red",size=8){
    ctx.strokeStyle = color;
    ctx.beginPath();
    ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
    ctx.stroke();
    }
    const polygon = poly();
    var activePoint,cursor;
    var dragging= false;
    function update(){
    if (mouse.update) {
    cursor = "crosshair";
    ctx.clearRect(0,0,canvas.width,canvas.height);
    if (!dragging) { activePoint = polygon.closest(mouse) }
    if (activePoint === undefined && mouse.button) {
    polygon.addPoint(mouse);
    mouse.button = false;
    } else if(activePoint) {
    if (mouse.button) {
    if(dragging) {
    activePoint.x += mouse.x - mouse.lx;
    activePoint.y += mouse.y - mouse.ly;
    } else { dragging = true }
    } else { dragging = false }
    }
    polygon.draw();
    if (activePoint) {
    drawCircle(activePoint);
    cursor = "move";
    }

    mouse.lx = mouse.x;
    mouse.ly = mouse.y;
    canvas.style.cursor = cursor;
    mouse.update = false;
    }
    requestAnimationFrame(update)
    }

    #canvas{
    border:1px
    solid black;
    }

    <canvas id="canvas" width=300 height=300></canvas>








    share|improve this answer




























      2














      The answer given is an example of bad practice in regard to handling the mouse and rendering content.



      Rendering from mouse events will chew power and force canvas renders when not needed. The mouse can fire at rates up to 1000 times a second while the max display rate is only 60 times a second.



      Using mouse move events means that many of the rendered updates will not be seen by the user, and are just wasted CPU/GPU cycles at best, at worst a major battery drain.



      Always use requestAnimationFrame to render any content that is frequently changing.



      The example below decoples the rendering from input events using requestAnimationFrame to render content only when needed. It also adds some feedback for the user via the cursor and highlighting points.






      var ctx = canvas.getContext("2d");
      requestAnimationFrame(update)

      mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
      function mouseEvents(e){
      const bounds = canvas.getBoundingClientRect();
      mouse.x = e.pageX - bounds.left - scrollX;
      mouse.y = e.pageY - bounds.top - scrollY;
      mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
      mouse.update = true;
      }
      ["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



      ctx.lineWidth = 2;
      ctx.strokeStyle = "blue";
      const point = (x,y) => ({x,y});
      const poly = () => ({
      points : ,
      addPoint(p){ this.points.push(point(p.x,p.y)) },
      draw() {
      ctx.lineWidth = 2;
      ctx.strokeStyle = "blue";
      ctx.beginPath();
      for (const p of this.points) { ctx.lineTo(p.x,p.y) }
      ctx.closePath();
      for (const p of this.points) {
      ctx.moveTo(p.x + 4,p.y);
      ctx.arc(p.x,p.y,4,0,Math.PI *2);
      }
      ctx.stroke();
      },
      closest(pos, dist = 8) {
      var i = 0, index = -1;
      dist *= dist;
      for (const p of this.points) {
      var x = pos.x - p.x;
      var y = pos.y - p.y;
      var d2 = x * x + y * y;
      if (d2 < dist) {
      dist = d2;
      index = i;
      }
      i++;
      }
      if (index > -1) { return this.points[index] }
      }
      });
      function drawCircle(pos,color="red",size=8){
      ctx.strokeStyle = color;
      ctx.beginPath();
      ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
      ctx.stroke();
      }
      const polygon = poly();
      var activePoint,cursor;
      var dragging= false;
      function update(){
      if (mouse.update) {
      cursor = "crosshair";
      ctx.clearRect(0,0,canvas.width,canvas.height);
      if (!dragging) { activePoint = polygon.closest(mouse) }
      if (activePoint === undefined && mouse.button) {
      polygon.addPoint(mouse);
      mouse.button = false;
      } else if(activePoint) {
      if (mouse.button) {
      if(dragging) {
      activePoint.x += mouse.x - mouse.lx;
      activePoint.y += mouse.y - mouse.ly;
      } else { dragging = true }
      } else { dragging = false }
      }
      polygon.draw();
      if (activePoint) {
      drawCircle(activePoint);
      cursor = "move";
      }

      mouse.lx = mouse.x;
      mouse.ly = mouse.y;
      canvas.style.cursor = cursor;
      mouse.update = false;
      }
      requestAnimationFrame(update)
      }

      #canvas{
      border:1px
      solid black;
      }

      <canvas id="canvas" width=300 height=300></canvas>








      share|improve this answer


























        2












        2








        2







        The answer given is an example of bad practice in regard to handling the mouse and rendering content.



        Rendering from mouse events will chew power and force canvas renders when not needed. The mouse can fire at rates up to 1000 times a second while the max display rate is only 60 times a second.



        Using mouse move events means that many of the rendered updates will not be seen by the user, and are just wasted CPU/GPU cycles at best, at worst a major battery drain.



        Always use requestAnimationFrame to render any content that is frequently changing.



        The example below decoples the rendering from input events using requestAnimationFrame to render content only when needed. It also adds some feedback for the user via the cursor and highlighting points.






        var ctx = canvas.getContext("2d");
        requestAnimationFrame(update)

        mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
        function mouseEvents(e){
        const bounds = canvas.getBoundingClientRect();
        mouse.x = e.pageX - bounds.left - scrollX;
        mouse.y = e.pageY - bounds.top - scrollY;
        mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
        mouse.update = true;
        }
        ["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        const point = (x,y) => ({x,y});
        const poly = () => ({
        points : ,
        addPoint(p){ this.points.push(point(p.x,p.y)) },
        draw() {
        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        ctx.beginPath();
        for (const p of this.points) { ctx.lineTo(p.x,p.y) }
        ctx.closePath();
        for (const p of this.points) {
        ctx.moveTo(p.x + 4,p.y);
        ctx.arc(p.x,p.y,4,0,Math.PI *2);
        }
        ctx.stroke();
        },
        closest(pos, dist = 8) {
        var i = 0, index = -1;
        dist *= dist;
        for (const p of this.points) {
        var x = pos.x - p.x;
        var y = pos.y - p.y;
        var d2 = x * x + y * y;
        if (d2 < dist) {
        dist = d2;
        index = i;
        }
        i++;
        }
        if (index > -1) { return this.points[index] }
        }
        });
        function drawCircle(pos,color="red",size=8){
        ctx.strokeStyle = color;
        ctx.beginPath();
        ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
        ctx.stroke();
        }
        const polygon = poly();
        var activePoint,cursor;
        var dragging= false;
        function update(){
        if (mouse.update) {
        cursor = "crosshair";
        ctx.clearRect(0,0,canvas.width,canvas.height);
        if (!dragging) { activePoint = polygon.closest(mouse) }
        if (activePoint === undefined && mouse.button) {
        polygon.addPoint(mouse);
        mouse.button = false;
        } else if(activePoint) {
        if (mouse.button) {
        if(dragging) {
        activePoint.x += mouse.x - mouse.lx;
        activePoint.y += mouse.y - mouse.ly;
        } else { dragging = true }
        } else { dragging = false }
        }
        polygon.draw();
        if (activePoint) {
        drawCircle(activePoint);
        cursor = "move";
        }

        mouse.lx = mouse.x;
        mouse.ly = mouse.y;
        canvas.style.cursor = cursor;
        mouse.update = false;
        }
        requestAnimationFrame(update)
        }

        #canvas{
        border:1px
        solid black;
        }

        <canvas id="canvas" width=300 height=300></canvas>








        share|improve this answer













        The answer given is an example of bad practice in regard to handling the mouse and rendering content.



        Rendering from mouse events will chew power and force canvas renders when not needed. The mouse can fire at rates up to 1000 times a second while the max display rate is only 60 times a second.



        Using mouse move events means that many of the rendered updates will not be seen by the user, and are just wasted CPU/GPU cycles at best, at worst a major battery drain.



        Always use requestAnimationFrame to render any content that is frequently changing.



        The example below decoples the rendering from input events using requestAnimationFrame to render content only when needed. It also adds some feedback for the user via the cursor and highlighting points.






        var ctx = canvas.getContext("2d");
        requestAnimationFrame(update)

        mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
        function mouseEvents(e){
        const bounds = canvas.getBoundingClientRect();
        mouse.x = e.pageX - bounds.left - scrollX;
        mouse.y = e.pageY - bounds.top - scrollY;
        mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
        mouse.update = true;
        }
        ["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        const point = (x,y) => ({x,y});
        const poly = () => ({
        points : ,
        addPoint(p){ this.points.push(point(p.x,p.y)) },
        draw() {
        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        ctx.beginPath();
        for (const p of this.points) { ctx.lineTo(p.x,p.y) }
        ctx.closePath();
        for (const p of this.points) {
        ctx.moveTo(p.x + 4,p.y);
        ctx.arc(p.x,p.y,4,0,Math.PI *2);
        }
        ctx.stroke();
        },
        closest(pos, dist = 8) {
        var i = 0, index = -1;
        dist *= dist;
        for (const p of this.points) {
        var x = pos.x - p.x;
        var y = pos.y - p.y;
        var d2 = x * x + y * y;
        if (d2 < dist) {
        dist = d2;
        index = i;
        }
        i++;
        }
        if (index > -1) { return this.points[index] }
        }
        });
        function drawCircle(pos,color="red",size=8){
        ctx.strokeStyle = color;
        ctx.beginPath();
        ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
        ctx.stroke();
        }
        const polygon = poly();
        var activePoint,cursor;
        var dragging= false;
        function update(){
        if (mouse.update) {
        cursor = "crosshair";
        ctx.clearRect(0,0,canvas.width,canvas.height);
        if (!dragging) { activePoint = polygon.closest(mouse) }
        if (activePoint === undefined && mouse.button) {
        polygon.addPoint(mouse);
        mouse.button = false;
        } else if(activePoint) {
        if (mouse.button) {
        if(dragging) {
        activePoint.x += mouse.x - mouse.lx;
        activePoint.y += mouse.y - mouse.ly;
        } else { dragging = true }
        } else { dragging = false }
        }
        polygon.draw();
        if (activePoint) {
        drawCircle(activePoint);
        cursor = "move";
        }

        mouse.lx = mouse.x;
        mouse.ly = mouse.y;
        canvas.style.cursor = cursor;
        mouse.update = false;
        }
        requestAnimationFrame(update)
        }

        #canvas{
        border:1px
        solid black;
        }

        <canvas id="canvas" width=300 height=300></canvas>








        var ctx = canvas.getContext("2d");
        requestAnimationFrame(update)

        mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
        function mouseEvents(e){
        const bounds = canvas.getBoundingClientRect();
        mouse.x = e.pageX - bounds.left - scrollX;
        mouse.y = e.pageY - bounds.top - scrollY;
        mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
        mouse.update = true;
        }
        ["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        const point = (x,y) => ({x,y});
        const poly = () => ({
        points : ,
        addPoint(p){ this.points.push(point(p.x,p.y)) },
        draw() {
        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        ctx.beginPath();
        for (const p of this.points) { ctx.lineTo(p.x,p.y) }
        ctx.closePath();
        for (const p of this.points) {
        ctx.moveTo(p.x + 4,p.y);
        ctx.arc(p.x,p.y,4,0,Math.PI *2);
        }
        ctx.stroke();
        },
        closest(pos, dist = 8) {
        var i = 0, index = -1;
        dist *= dist;
        for (const p of this.points) {
        var x = pos.x - p.x;
        var y = pos.y - p.y;
        var d2 = x * x + y * y;
        if (d2 < dist) {
        dist = d2;
        index = i;
        }
        i++;
        }
        if (index > -1) { return this.points[index] }
        }
        });
        function drawCircle(pos,color="red",size=8){
        ctx.strokeStyle = color;
        ctx.beginPath();
        ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
        ctx.stroke();
        }
        const polygon = poly();
        var activePoint,cursor;
        var dragging= false;
        function update(){
        if (mouse.update) {
        cursor = "crosshair";
        ctx.clearRect(0,0,canvas.width,canvas.height);
        if (!dragging) { activePoint = polygon.closest(mouse) }
        if (activePoint === undefined && mouse.button) {
        polygon.addPoint(mouse);
        mouse.button = false;
        } else if(activePoint) {
        if (mouse.button) {
        if(dragging) {
        activePoint.x += mouse.x - mouse.lx;
        activePoint.y += mouse.y - mouse.ly;
        } else { dragging = true }
        } else { dragging = false }
        }
        polygon.draw();
        if (activePoint) {
        drawCircle(activePoint);
        cursor = "move";
        }

        mouse.lx = mouse.x;
        mouse.ly = mouse.y;
        canvas.style.cursor = cursor;
        mouse.update = false;
        }
        requestAnimationFrame(update)
        }

        #canvas{
        border:1px
        solid black;
        }

        <canvas id="canvas" width=300 height=300></canvas>





        var ctx = canvas.getContext("2d");
        requestAnimationFrame(update)

        mouse = {x : 0, y : 0, button : 0, lx : 0, ly : 0, update : true};
        function mouseEvents(e){
        const bounds = canvas.getBoundingClientRect();
        mouse.x = e.pageX - bounds.left - scrollX;
        mouse.y = e.pageY - bounds.top - scrollY;
        mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
        mouse.update = true;
        }
        ["mousedown","mouseup","mousemove"].forEach(name => document.addEventListener(name,mouseEvents));



        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        const point = (x,y) => ({x,y});
        const poly = () => ({
        points : ,
        addPoint(p){ this.points.push(point(p.x,p.y)) },
        draw() {
        ctx.lineWidth = 2;
        ctx.strokeStyle = "blue";
        ctx.beginPath();
        for (const p of this.points) { ctx.lineTo(p.x,p.y) }
        ctx.closePath();
        for (const p of this.points) {
        ctx.moveTo(p.x + 4,p.y);
        ctx.arc(p.x,p.y,4,0,Math.PI *2);
        }
        ctx.stroke();
        },
        closest(pos, dist = 8) {
        var i = 0, index = -1;
        dist *= dist;
        for (const p of this.points) {
        var x = pos.x - p.x;
        var y = pos.y - p.y;
        var d2 = x * x + y * y;
        if (d2 < dist) {
        dist = d2;
        index = i;
        }
        i++;
        }
        if (index > -1) { return this.points[index] }
        }
        });
        function drawCircle(pos,color="red",size=8){
        ctx.strokeStyle = color;
        ctx.beginPath();
        ctx.arc(pos.x,pos.y,size,0,Math.PI *2);
        ctx.stroke();
        }
        const polygon = poly();
        var activePoint,cursor;
        var dragging= false;
        function update(){
        if (mouse.update) {
        cursor = "crosshair";
        ctx.clearRect(0,0,canvas.width,canvas.height);
        if (!dragging) { activePoint = polygon.closest(mouse) }
        if (activePoint === undefined && mouse.button) {
        polygon.addPoint(mouse);
        mouse.button = false;
        } else if(activePoint) {
        if (mouse.button) {
        if(dragging) {
        activePoint.x += mouse.x - mouse.lx;
        activePoint.y += mouse.y - mouse.ly;
        } else { dragging = true }
        } else { dragging = false }
        }
        polygon.draw();
        if (activePoint) {
        drawCircle(activePoint);
        cursor = "move";
        }

        mouse.lx = mouse.x;
        mouse.ly = mouse.y;
        canvas.style.cursor = cursor;
        mouse.update = false;
        }
        requestAnimationFrame(update)
        }

        #canvas{
        border:1px
        solid black;
        }

        <canvas id="canvas" width=300 height=300></canvas>






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 22 '18 at 21:02









        Blindman67Blindman67

        26.7k52763




        26.7k52763

























            2














            I've made a few changes to your code. Since I need to detect the position of the mouse I've added a function to do this.



            The logic is as it follows:




            1. you draw the points.


            2. When you are done you can begin to drag the points


            3. If you click inside a point (a small circle around the point) you save the index of the point.


            4. on mouse move you move the point you clicked in.


            5. on mouse up no point is dragged anymore.



            I hope this is what you need.






            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var cw = canvas.width;
            var ch = canvas.height;
            var mouse = {};
            var draggable = false;

            context.lineWidth = 2;
            context.strokeStyle = "blue";

            var coordinates = ;
            var isDone = false;

            done.addEventListener("click", function() {
            isDone = true;
            });

            canvas.addEventListener("mousedown", function(e) {
            handleMouseDown(e);
            });

            function handleMouseDown(e) {
            mouse = oMousePos(canvas, e);
            //if isDone you can drag
            if (isDone || coordinates.length > 10) {
            for (index = 0; index < coordinates.length; index++) {
            // you draw a small circle no stroke, no fill
            context.beginPath();
            context.arc(
            coordinates[index].x,
            coordinates[index].y,
            5,
            0,
            2 * Math.PI
            );
            // if the mouse is inside the circle
            if (context.isPointInPath(mouse.x, mouse.y)) {
            // you can drag this point
            // I'm using index + 1 because index == 0 is false
            draggable = index + 1;
            // if I have a point a can break the loop
            break;
            }
            }
            } else {
            coordinates.push({ x: mouse.x, y: mouse.y });
            drawPolygon();
            }
            }

            function drawPolygon() {
            context.clearRect(0, 0, cw, ch);
            context.beginPath();
            context.moveTo(coordinates[0].x, coordinates[0].y);
            for (index = 1; index < coordinates.length; index++) {
            context.lineTo(coordinates[index].x, coordinates[index].y);
            }
            context.closePath();
            context.stroke();
            // Additionaly I'm drawing a small circle around every point
            // you can delete this.
            for (index = 0; index < coordinates.length; index++) {
            context.beginPath();
            context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
            context.stroke();
            }
            }

            canvas.addEventListener("mousemove", function(e) {
            if (isDone) {
            if (draggable) {
            mouse = oMousePos(canvas, e);
            // draggable - 1 is the index of the point in the coordinates array
            coordinates[draggable - 1].x = mouse.x;
            coordinates[draggable - 1].y = mouse.y;
            drawPolygon();
            }
            }
            });

            canvas.addEventListener("mouseup", function(e) {
            if (draggable) {
            draggable = false;
            }
            });


            // a function to detect the mouse position

            function oMousePos(canvas, evt) {
            var ClientRect = canvas.getBoundingClientRect();
            return {
            //objeto
            x: Math.round(evt.clientX - ClientRect.left),
            y: Math.round(evt.clientY - ClientRect.top)
            };
            }

            body{ background-color: ivory; }
            #canvas{border:1px solid red;}

            <h4>Click to assign polygon vertices</h4>
            <button id=done>Click when done assigning points</button>
            <br><canvas id="canvas" width=300 height=300></canvas>








            share|improve this answer
























            • Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

              – sonia maklouf
              Nov 22 '18 at 15:10











            • coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

              – enxaneta
              Nov 22 '18 at 18:18
















            2














            I've made a few changes to your code. Since I need to detect the position of the mouse I've added a function to do this.



            The logic is as it follows:




            1. you draw the points.


            2. When you are done you can begin to drag the points


            3. If you click inside a point (a small circle around the point) you save the index of the point.


            4. on mouse move you move the point you clicked in.


            5. on mouse up no point is dragged anymore.



            I hope this is what you need.






            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var cw = canvas.width;
            var ch = canvas.height;
            var mouse = {};
            var draggable = false;

            context.lineWidth = 2;
            context.strokeStyle = "blue";

            var coordinates = ;
            var isDone = false;

            done.addEventListener("click", function() {
            isDone = true;
            });

            canvas.addEventListener("mousedown", function(e) {
            handleMouseDown(e);
            });

            function handleMouseDown(e) {
            mouse = oMousePos(canvas, e);
            //if isDone you can drag
            if (isDone || coordinates.length > 10) {
            for (index = 0; index < coordinates.length; index++) {
            // you draw a small circle no stroke, no fill
            context.beginPath();
            context.arc(
            coordinates[index].x,
            coordinates[index].y,
            5,
            0,
            2 * Math.PI
            );
            // if the mouse is inside the circle
            if (context.isPointInPath(mouse.x, mouse.y)) {
            // you can drag this point
            // I'm using index + 1 because index == 0 is false
            draggable = index + 1;
            // if I have a point a can break the loop
            break;
            }
            }
            } else {
            coordinates.push({ x: mouse.x, y: mouse.y });
            drawPolygon();
            }
            }

            function drawPolygon() {
            context.clearRect(0, 0, cw, ch);
            context.beginPath();
            context.moveTo(coordinates[0].x, coordinates[0].y);
            for (index = 1; index < coordinates.length; index++) {
            context.lineTo(coordinates[index].x, coordinates[index].y);
            }
            context.closePath();
            context.stroke();
            // Additionaly I'm drawing a small circle around every point
            // you can delete this.
            for (index = 0; index < coordinates.length; index++) {
            context.beginPath();
            context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
            context.stroke();
            }
            }

            canvas.addEventListener("mousemove", function(e) {
            if (isDone) {
            if (draggable) {
            mouse = oMousePos(canvas, e);
            // draggable - 1 is the index of the point in the coordinates array
            coordinates[draggable - 1].x = mouse.x;
            coordinates[draggable - 1].y = mouse.y;
            drawPolygon();
            }
            }
            });

            canvas.addEventListener("mouseup", function(e) {
            if (draggable) {
            draggable = false;
            }
            });


            // a function to detect the mouse position

            function oMousePos(canvas, evt) {
            var ClientRect = canvas.getBoundingClientRect();
            return {
            //objeto
            x: Math.round(evt.clientX - ClientRect.left),
            y: Math.round(evt.clientY - ClientRect.top)
            };
            }

            body{ background-color: ivory; }
            #canvas{border:1px solid red;}

            <h4>Click to assign polygon vertices</h4>
            <button id=done>Click when done assigning points</button>
            <br><canvas id="canvas" width=300 height=300></canvas>








            share|improve this answer
























            • Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

              – sonia maklouf
              Nov 22 '18 at 15:10











            • coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

              – enxaneta
              Nov 22 '18 at 18:18














            2












            2








            2







            I've made a few changes to your code. Since I need to detect the position of the mouse I've added a function to do this.



            The logic is as it follows:




            1. you draw the points.


            2. When you are done you can begin to drag the points


            3. If you click inside a point (a small circle around the point) you save the index of the point.


            4. on mouse move you move the point you clicked in.


            5. on mouse up no point is dragged anymore.



            I hope this is what you need.






            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var cw = canvas.width;
            var ch = canvas.height;
            var mouse = {};
            var draggable = false;

            context.lineWidth = 2;
            context.strokeStyle = "blue";

            var coordinates = ;
            var isDone = false;

            done.addEventListener("click", function() {
            isDone = true;
            });

            canvas.addEventListener("mousedown", function(e) {
            handleMouseDown(e);
            });

            function handleMouseDown(e) {
            mouse = oMousePos(canvas, e);
            //if isDone you can drag
            if (isDone || coordinates.length > 10) {
            for (index = 0; index < coordinates.length; index++) {
            // you draw a small circle no stroke, no fill
            context.beginPath();
            context.arc(
            coordinates[index].x,
            coordinates[index].y,
            5,
            0,
            2 * Math.PI
            );
            // if the mouse is inside the circle
            if (context.isPointInPath(mouse.x, mouse.y)) {
            // you can drag this point
            // I'm using index + 1 because index == 0 is false
            draggable = index + 1;
            // if I have a point a can break the loop
            break;
            }
            }
            } else {
            coordinates.push({ x: mouse.x, y: mouse.y });
            drawPolygon();
            }
            }

            function drawPolygon() {
            context.clearRect(0, 0, cw, ch);
            context.beginPath();
            context.moveTo(coordinates[0].x, coordinates[0].y);
            for (index = 1; index < coordinates.length; index++) {
            context.lineTo(coordinates[index].x, coordinates[index].y);
            }
            context.closePath();
            context.stroke();
            // Additionaly I'm drawing a small circle around every point
            // you can delete this.
            for (index = 0; index < coordinates.length; index++) {
            context.beginPath();
            context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
            context.stroke();
            }
            }

            canvas.addEventListener("mousemove", function(e) {
            if (isDone) {
            if (draggable) {
            mouse = oMousePos(canvas, e);
            // draggable - 1 is the index of the point in the coordinates array
            coordinates[draggable - 1].x = mouse.x;
            coordinates[draggable - 1].y = mouse.y;
            drawPolygon();
            }
            }
            });

            canvas.addEventListener("mouseup", function(e) {
            if (draggable) {
            draggable = false;
            }
            });


            // a function to detect the mouse position

            function oMousePos(canvas, evt) {
            var ClientRect = canvas.getBoundingClientRect();
            return {
            //objeto
            x: Math.round(evt.clientX - ClientRect.left),
            y: Math.round(evt.clientY - ClientRect.top)
            };
            }

            body{ background-color: ivory; }
            #canvas{border:1px solid red;}

            <h4>Click to assign polygon vertices</h4>
            <button id=done>Click when done assigning points</button>
            <br><canvas id="canvas" width=300 height=300></canvas>








            share|improve this answer













            I've made a few changes to your code. Since I need to detect the position of the mouse I've added a function to do this.



            The logic is as it follows:




            1. you draw the points.


            2. When you are done you can begin to drag the points


            3. If you click inside a point (a small circle around the point) you save the index of the point.


            4. on mouse move you move the point you clicked in.


            5. on mouse up no point is dragged anymore.



            I hope this is what you need.






            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var cw = canvas.width;
            var ch = canvas.height;
            var mouse = {};
            var draggable = false;

            context.lineWidth = 2;
            context.strokeStyle = "blue";

            var coordinates = ;
            var isDone = false;

            done.addEventListener("click", function() {
            isDone = true;
            });

            canvas.addEventListener("mousedown", function(e) {
            handleMouseDown(e);
            });

            function handleMouseDown(e) {
            mouse = oMousePos(canvas, e);
            //if isDone you can drag
            if (isDone || coordinates.length > 10) {
            for (index = 0; index < coordinates.length; index++) {
            // you draw a small circle no stroke, no fill
            context.beginPath();
            context.arc(
            coordinates[index].x,
            coordinates[index].y,
            5,
            0,
            2 * Math.PI
            );
            // if the mouse is inside the circle
            if (context.isPointInPath(mouse.x, mouse.y)) {
            // you can drag this point
            // I'm using index + 1 because index == 0 is false
            draggable = index + 1;
            // if I have a point a can break the loop
            break;
            }
            }
            } else {
            coordinates.push({ x: mouse.x, y: mouse.y });
            drawPolygon();
            }
            }

            function drawPolygon() {
            context.clearRect(0, 0, cw, ch);
            context.beginPath();
            context.moveTo(coordinates[0].x, coordinates[0].y);
            for (index = 1; index < coordinates.length; index++) {
            context.lineTo(coordinates[index].x, coordinates[index].y);
            }
            context.closePath();
            context.stroke();
            // Additionaly I'm drawing a small circle around every point
            // you can delete this.
            for (index = 0; index < coordinates.length; index++) {
            context.beginPath();
            context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
            context.stroke();
            }
            }

            canvas.addEventListener("mousemove", function(e) {
            if (isDone) {
            if (draggable) {
            mouse = oMousePos(canvas, e);
            // draggable - 1 is the index of the point in the coordinates array
            coordinates[draggable - 1].x = mouse.x;
            coordinates[draggable - 1].y = mouse.y;
            drawPolygon();
            }
            }
            });

            canvas.addEventListener("mouseup", function(e) {
            if (draggable) {
            draggable = false;
            }
            });


            // a function to detect the mouse position

            function oMousePos(canvas, evt) {
            var ClientRect = canvas.getBoundingClientRect();
            return {
            //objeto
            x: Math.round(evt.clientX - ClientRect.left),
            y: Math.round(evt.clientY - ClientRect.top)
            };
            }

            body{ background-color: ivory; }
            #canvas{border:1px solid red;}

            <h4>Click to assign polygon vertices</h4>
            <button id=done>Click when done assigning points</button>
            <br><canvas id="canvas" width=300 height=300></canvas>








            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var cw = canvas.width;
            var ch = canvas.height;
            var mouse = {};
            var draggable = false;

            context.lineWidth = 2;
            context.strokeStyle = "blue";

            var coordinates = ;
            var isDone = false;

            done.addEventListener("click", function() {
            isDone = true;
            });

            canvas.addEventListener("mousedown", function(e) {
            handleMouseDown(e);
            });

            function handleMouseDown(e) {
            mouse = oMousePos(canvas, e);
            //if isDone you can drag
            if (isDone || coordinates.length > 10) {
            for (index = 0; index < coordinates.length; index++) {
            // you draw a small circle no stroke, no fill
            context.beginPath();
            context.arc(
            coordinates[index].x,
            coordinates[index].y,
            5,
            0,
            2 * Math.PI
            );
            // if the mouse is inside the circle
            if (context.isPointInPath(mouse.x, mouse.y)) {
            // you can drag this point
            // I'm using index + 1 because index == 0 is false
            draggable = index + 1;
            // if I have a point a can break the loop
            break;
            }
            }
            } else {
            coordinates.push({ x: mouse.x, y: mouse.y });
            drawPolygon();
            }
            }

            function drawPolygon() {
            context.clearRect(0, 0, cw, ch);
            context.beginPath();
            context.moveTo(coordinates[0].x, coordinates[0].y);
            for (index = 1; index < coordinates.length; index++) {
            context.lineTo(coordinates[index].x, coordinates[index].y);
            }
            context.closePath();
            context.stroke();
            // Additionaly I'm drawing a small circle around every point
            // you can delete this.
            for (index = 0; index < coordinates.length; index++) {
            context.beginPath();
            context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
            context.stroke();
            }
            }

            canvas.addEventListener("mousemove", function(e) {
            if (isDone) {
            if (draggable) {
            mouse = oMousePos(canvas, e);
            // draggable - 1 is the index of the point in the coordinates array
            coordinates[draggable - 1].x = mouse.x;
            coordinates[draggable - 1].y = mouse.y;
            drawPolygon();
            }
            }
            });

            canvas.addEventListener("mouseup", function(e) {
            if (draggable) {
            draggable = false;
            }
            });


            // a function to detect the mouse position

            function oMousePos(canvas, evt) {
            var ClientRect = canvas.getBoundingClientRect();
            return {
            //objeto
            x: Math.round(evt.clientX - ClientRect.left),
            y: Math.round(evt.clientY - ClientRect.top)
            };
            }

            body{ background-color: ivory; }
            #canvas{border:1px solid red;}

            <h4>Click to assign polygon vertices</h4>
            <button id=done>Click when done assigning points</button>
            <br><canvas id="canvas" width=300 height=300></canvas>





            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var cw = canvas.width;
            var ch = canvas.height;
            var mouse = {};
            var draggable = false;

            context.lineWidth = 2;
            context.strokeStyle = "blue";

            var coordinates = ;
            var isDone = false;

            done.addEventListener("click", function() {
            isDone = true;
            });

            canvas.addEventListener("mousedown", function(e) {
            handleMouseDown(e);
            });

            function handleMouseDown(e) {
            mouse = oMousePos(canvas, e);
            //if isDone you can drag
            if (isDone || coordinates.length > 10) {
            for (index = 0; index < coordinates.length; index++) {
            // you draw a small circle no stroke, no fill
            context.beginPath();
            context.arc(
            coordinates[index].x,
            coordinates[index].y,
            5,
            0,
            2 * Math.PI
            );
            // if the mouse is inside the circle
            if (context.isPointInPath(mouse.x, mouse.y)) {
            // you can drag this point
            // I'm using index + 1 because index == 0 is false
            draggable = index + 1;
            // if I have a point a can break the loop
            break;
            }
            }
            } else {
            coordinates.push({ x: mouse.x, y: mouse.y });
            drawPolygon();
            }
            }

            function drawPolygon() {
            context.clearRect(0, 0, cw, ch);
            context.beginPath();
            context.moveTo(coordinates[0].x, coordinates[0].y);
            for (index = 1; index < coordinates.length; index++) {
            context.lineTo(coordinates[index].x, coordinates[index].y);
            }
            context.closePath();
            context.stroke();
            // Additionaly I'm drawing a small circle around every point
            // you can delete this.
            for (index = 0; index < coordinates.length; index++) {
            context.beginPath();
            context.arc(coordinates[index].x, coordinates[index].y, 5, 0, 2 * Math.PI);
            context.stroke();
            }
            }

            canvas.addEventListener("mousemove", function(e) {
            if (isDone) {
            if (draggable) {
            mouse = oMousePos(canvas, e);
            // draggable - 1 is the index of the point in the coordinates array
            coordinates[draggable - 1].x = mouse.x;
            coordinates[draggable - 1].y = mouse.y;
            drawPolygon();
            }
            }
            });

            canvas.addEventListener("mouseup", function(e) {
            if (draggable) {
            draggable = false;
            }
            });


            // a function to detect the mouse position

            function oMousePos(canvas, evt) {
            var ClientRect = canvas.getBoundingClientRect();
            return {
            //objeto
            x: Math.round(evt.clientX - ClientRect.left),
            y: Math.round(evt.clientY - ClientRect.top)
            };
            }

            body{ background-color: ivory; }
            #canvas{border:1px solid red;}

            <h4>Click to assign polygon vertices</h4>
            <button id=done>Click when done assigning points</button>
            <br><canvas id="canvas" width=300 height=300></canvas>






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 22 '18 at 14:39









            enxanetaenxaneta

            8,3322518




            8,3322518













            • Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

              – sonia maklouf
              Nov 22 '18 at 15:10











            • coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

              – enxaneta
              Nov 22 '18 at 18:18



















            • Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

              – sonia maklouf
              Nov 22 '18 at 15:10











            • coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

              – enxaneta
              Nov 22 '18 at 18:18

















            Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

            – sonia maklouf
            Nov 22 '18 at 15:10





            Thanks for your answer I just wonder why you do coordinates.length > 10 for handleMouseDown function ?

            – sonia maklouf
            Nov 22 '18 at 15:10













            coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

            – enxaneta
            Nov 22 '18 at 18:18





            coordinates.length > 10 was in your code. I supposed you wanted to limit the number of your points.

            – enxaneta
            Nov 22 '18 at 18:18


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427699%2fediting-selections-of-path-points-or-line%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            If I really need a card on my start hand, how many mulligans make sense? [duplicate]

            Alcedinidae

            Can an atomic nucleus contain both particles and antiparticles? [duplicate]