如何使用 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
目前我有这个 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