我是 javascript 新手,我正在使用 arbor.js 所以创建一个图表,但我希望能够根据邻近度连接节点或能够拖动边来连接节点。我已将一个 json 文件链接到包含节点信息的 js。
我对此并不陌生,这似乎是一项非常艰巨的任务,任何有助于获得正确方向的帮助将不胜感激。
这是 halfviz 演示的一部分 renderer.js 代码。这是我的自定义图表:http ://arborjs.org/halfviz/#/NTQ5Ng
// draw the edges
particleSystem.eachEdge(function(edge, pt1, pt2){
// edge: {source:Node, target:Node, length:#, data:{}}
// pt1: {x:#, y:#} source position in screen coords
// pt2: {x:#, y:#} target position in screen coords
var weight = edge.data.weight
var color = edge.data.color
if (!color || (""+color).match(/^[ \t]*$/)) color = null
// find the start point
var tail = intersect_line_box(pt1, pt2, nodeBoxes[edge.source.name])
var head = intersect_line_box(tail, pt2, nodeBoxes[edge.target.name])
ctx.save()
ctx.beginPath()
ctx.lineWidth = (!isNaN(weight)) ? parseFloat(weight) : 1
ctx.strokeStyle = (color) ? color : "#cccccc"
ctx.fillStyle = null
ctx.moveTo(tail.x, tail.y)
ctx.lineTo(head.x, head.y)
ctx.stroke()
ctx.restore()
// draw an arrowhead if this is a -> style edge
if (edge.data.directed){
ctx.save()
// move to the head position of the edge we just drew
var wt = !isNaN(weight) ? parseFloat(weight) : 1
var arrowLength = 6 + wt
var arrowWidth = 2 + wt
ctx.fillStyle = (color) ? color : "#cccccc"
ctx.translate(head.x, head.y);
ctx.rotate(Math.atan2(head.y - tail.y, head.x - tail.x));
// delete some of the edge that's already there (so the point isn't hidden)
ctx.clearRect(-arrowLength/2,-wt/2, arrowLength/2,wt)
// draw the chevron
ctx.beginPath();
ctx.moveTo(-arrowLength, arrowWidth);
ctx.lineTo(0, 0);
ctx.lineTo(-arrowLength, -arrowWidth);
ctx.lineTo(-arrowLength * 0.8, -0);
ctx.closePath();
ctx.fill();
ctx.restore()
}
})
},
initMouseHandling:function(){
// no-nonsense drag and drop (thanks springy.js)
selected = null;
nearest = null;
var dragged = null;
var oldmass = 1
// set up a handler object that will initially listen for mousedowns then
// for moves and mouseups while dragging
var handler = {
clicked:function(e){
var pos = $(canvas).offset();
_mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)
selected = nearest = dragged = particleSystem.nearest(_mouseP);
if (dragged.node !== null) dragged.node.fixed = true
$(canvas).bind('mousemove', handler.dragged)
$(window).bind('mouseup', handler.dropped)
return false
},
dragged:function(e){
var old_nearest = nearest && nearest.node._id
var pos = $(canvas).offset();
var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)
if (!nearest) return
if (dragged !== null && dragged.node !== null){
var p = particleSystem.fromScreen(s)
dragged.node.p = p
}
return false
},
dropped:function(e){
if (dragged===null || dragged.node===undefined) return
if (dragged.node !== null) dragged.node.fixed = false
dragged.node.tempMass = 1000
dragged = null
selected = null
$(canvas).unbind('mousemove', handler.dragged)
$(window).unbind('mouseup', handler.dropped)
_mouseP = null
return false
}
}
$(canvas).mousedown(handler.clicked);
}
}
// helpers for figuring out where to draw arrows (thanks springy.js)
var intersect_line_line = function(p1, p2, p3, p4)
{
var denom = ((p4.y - p3.y)*(p2.x - p1.x) - (p4.x - p3.x)*(p2.y - p1.y));
if (denom === 0) return false // lines are parallel
var ua = ((p4.x - p3.x)*(p1.y - p3.y) - (p4.y - p3.y)*(p1.x - p3.x)) / denom;
var ub = ((p2.x - p1.x)*(p1.y - p3.y) - (p2.y - p1.y)*(p1.x - p3.x)) / denom;
if (ua < 0 || ua > 1 || ub < 0 || ub > 1) return false
return arbor.Point(p1.x + ua * (p2.x - p1.x), p1.y + ua * (p2.y - p1.y));
}
var intersect_line_box = function(p1, p2, boxTuple)
{
var p3 = {x:boxTuple[0], y:boxTuple[1]},
w = boxTuple[2],
h = boxTuple[3]
var tl = {x: p3.x, y: p3.y};
var tr = {x: p3.x + w, y: p3.y};
var bl = {x: p3.x, y: p3.y + h};
var br = {x: p3.x + w, y: p3.y + h};
return intersect_line_line(p1, p2, tl, tr) ||
intersect_line_line(p1, p2, tr, br) ||
intersect_line_line(p1, p2, br, bl) ||
intersect_line_line(p1, p2, bl, tl) ||
false
}
return that
}
})()