arbor.js allows you to write code to display the entire graph. You can do whatever you want in the rendering method, including the edge drawings that you can store on a separate map.
Just override the rendering method in Renderer as follows:
redraw:function() { ctx.fillStyle = "white"; ctx.fillRect (0,0, canvas.width, canvas.height); particleSystem.eachEdge (function (edge, pt1, pt2) { ctx.strokeStyle = "rgba(0,0,0, .333)"; ctx.lineWidth = 1; ctx.beginPath (); ctx.moveTo (pt1.x, pt1.y); ctx.lineTo (pt2.x, pt2.y); ctx.stroke (); ctx.fillStyle = "black"; ctx.font = 'italic 13px sans-serif'; ctx.fillText (edge.data.name, (pt1.x + pt2.x) / 2, (pt1.y + pt2.y) / 2); }); particleSystem.eachNode (function (node, pt) { var w = 10; ctx.fillStyle = "orange"; ctx.fillRect (pt.xw/2, pt.yw/2, w,w); ctx.fillStyle = "black"; ctx.font = 'italic 13px sans-serif'; ctx.fillText (node.name, pt.x+8, pt.y+8); }); };
This code expects data properties for each edge that must be filled during initialization.
I create all nodes and edges manually using my own map and addNode / addEdge methods, suppose you can change your code a bit to initialize edges using custom data as follows:
var theUI = { nodes:{A:{color:"red", shape:"dot", alpha:1}, B:{color:"#b2b19d", shape:"dot", alpha:1}, C:{color:"#b2b19d", shape:"dot", alpha:1}, D:{color:"#b2b19d", shape:"dot", alpha:1}, }, edges:{ A:{ B:{length:.8, data:{name:"A->B"}}, C:{length:.8, data:{name:"A->C"}}, D:{length:.8, data:{name:"A->D"}} } } }
PS: look at this example , I learned a lot from him.