我正在尝试找到一种方法来通过使用鼠标单击选择路径点来在html5 Canvas 中拖放带有JavaScript的多边形点或线

如下图所示
javascript - 编辑路径点或线的选择-LMLPHP

通过单击并将其拖动到新位置来移动所选点

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>

最佳答案

给出的答案是有关处理鼠标和呈现内容的不良做法的一个示例。

鼠标事件的渲染将消耗能量并在不需要时强制 Canvas 渲染。鼠标可以每秒高达1000次的速率发射,而最大显示速率仅为每秒60次。

使用鼠标移动事件意味着许多渲染的更新将不会被用户看到,并且充其量只会充其量浪费CPU / GPU周期,最糟糕的是会浪费大量电池。

始终使用requestAnimationFrame呈现任何经常更改的内容。

下面的示例使用requestAnimationFrame从输入事件中取消渲染渲染,以仅在需要时渲染内容。它还通过光标和突出显示点为用户添加了一些反馈。

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>

09-11 20:35