如何使用 html5-canvas 拖动连接线

How to drag connected lines using html5-canvas

目前我有这个 sample 创建四个点,然后连接它。

基本上我想要的是当你点击一条线时拖动线的整个连接(区域)但是当你选择圆圈时它应该被扩展(已经实现)

for(var i=0;i<connectors.length;i++){
    var c=connectors[i];
    var s=anchors[c.start];
    var e=anchors[c.end];
    ctx.beginPath();
    ctx.moveTo(s.x,s.y);
    ctx.lineTo(e.x,e.y);
    ctx.stroke();
}   

// draw circles
for(var i=0;i<anchors.length;i++){
    ctx.beginPath();
    ctx.arc(anchors[i].x,anchors[i].y,radius,0,Math.PI*2);
    ctx.fill(); 
    ctx.fillText(anchors[i].label,anchors[i].x-5,anchors[i].y-15); 
}`

你有 2 个重要步骤必须解决这个问题:

1 - 检测鼠标在按住 LMB 时是否在一条线上。

2 - 移动鼠标时移动连接到相关行的所有点。

检测一个点是否在一条直线上

理论:从数学上讲,如果一个点到直线两端的距离等于直线两端之间的距离,则可以检测该点是否在(封闭的)线上线.

更多信息:here

我写了一个小函数来检查这个:

function mouseOnLine(mousePos) {

    for (var i = 0 ; i < connectors.length; i++){
        var pA = anchors[connectors[i].start];
        var pB = anchors[connectors[i].end];

        var first = distanceBetween(pA,mousePos) + distanceBetween(pB,mousePos);
        var second = distanceBetween(pA,pB);
        if (Math.abs(first - second) < 0.3) //Threshold of 0.3
            return connectors[i];

    }

    return null;
}

重要提示:我不检查它是否等于 0,而是检查差值是否小于 0.3,因此鼠标不必正好在直线上,因为那会很困难实现。

之间的距离是一个简单的毕达哥拉斯计算:

var distanceBetween = function (point1, point2) {

    var distX = Math.abs( point1.x - point2.x);
    var distY = Math.abs(point1.y - point2.y);
    return Math.sqrt((distX * distX) + (distY * distY));
}

移动所有与此相连的点

理论:一旦我们检测到鼠标按钮被按住在一条线上,我们就必须找到该表格的第一个点。我们知道每个多边形包含 4 个点,所以我们可以循环接下来的 4 个点。

我们可以通过一点计算找到多边形的第一个点(假设它们总是有序的):

var startPoints = Math.floor(fullDrag.start / 4) * 4;
//Example: We clicked on the line starting with point 3. this will return:
//Math.floor(3 / 4) * 4  ==> Math.floor(0.75) * 4 ==> 0 * 4 ==> 0

现在循环并移动它:

var startPoints = Math.floor(fullDrag.start / 4) * 4;
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);

for (var i = 0; i < 4; i++) {
    anchors[startPoints+i].x +=(mouseX-startX);
    anchors[startPoints+i].y +=(mouseY-startY);
}

startX=mouseX;
startY=mouseY; 

阅读这篇文章的其他人:上面显示的代码只是整个解决方案的片段。你可以找到一个有效的 fiddle right here