Forçage dirigé de graphes multiples arêtes utilisant la trame d3

J’ai créé un graphe dirigé forcé qui a plusieurs arêtes, mais après le rendu, il montre seulement, un autre chevauche l’autre. Je veux créer quelque chose comme https://bl.ocks.org/mattkohl/146d301c0fc20d89d85880df537de7b0#index.html

Mon code: JSBIN

   Sample Graph Rendring Using Canvas      var graph = {}//randomgraph.WattsStrogatz.beta(15, 4, 0.06); graph.nodes = [{"label":"x"} , {"label":"y"}]; graph.edges = [{source:0,target:1},{source:0,target:1}, {source:1,target:0}] var canvas = null var width = window.innerWidth, height = window.innerHeight; canvas = d3.select("body").append("canvas").attr("width",width).attr("height",height); var context = canvas.node().getContext("2d"); force = d3.forceSimulation() .force("link", d3.forceLink().id(function(d) { return d.index; })).force("charge", d3.forceManyBody()) .force("center", d3.forceCenter(width / 2, height / 2)); force.nodes(graph.nodes); force.force("link").links(graph.edges).distance(200); var detachedContainer = document.createElement("custom"); dataContainer = d3.select(detachedContainer); link = dataContainer.selectAll(".link").data(graph.edges) .enter().append("line").attr("class", "link") .style("stroke-width", 2) node = dataContainer.selectAll(".node").data(graph.nodes) .enter().append("g"); var circles = node.append("circle") .classed("circle-class", true) .attr("class", function (d){ return "node node_" + d.index;}) .attr("r", 5) .attr("fill", 'red') .attr("strokeStyle", 'black'); d3.timer(function(){ context.clearRect(0, 0, width, height); // draw links link.each(function(d) { context.strokeStyle = "#ccc"; /***** Elliptical arcs *****/ context.stroke(new Path2D(linkArc(d))); /***** Elliptical arcs *****/ }); context.lineWidth = 2; node.each(function(d) { context.beginPath(); context.moveTo(dx, dy); var r = d3.select(this).select("circle").node().getAtsortingbute('r'); dx = Math.max(30, Math.min(width - 30, dx)); dy = Math.max(30, Math.min(height - 30, dy)); context.closePath(); context.arc(dx, dy, r, 0, 2 * Math.PI); context.fillStyle = d3.select(this).select("circle").node().getAtsortingbute('fill'); context.strokeStyle = d3.select(this).select("circle").node().getAtsortingbute('strokeStyle'); context.stroke(); context.fill(); context.beginPath(); context.arc(dx + 15, dy-20, 5, 0, 2 * Math.PI); context.fillStyle = "orange"; context.strokeStyle = "orange"; var data = d3.select(this).data(); context.stroke(); context.fill(); context.font = "10px Arial"; context.fillStyle = "black"; context.strokeStyle = "black"; context.fillText(parseInt(data[0].index),dx + 10, dy-15); }); }); circles.transition().duration(5000).attr('r', 20).attr('fill', 'orange'); canvas.node().addEventListener('click',function( event ){ console.log(event) // Its COMING ANY TIME INSIDE ON CLICK OF CANVAS }); /***** Elliptical arcs *****/ function linkArc(d) { var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math.sqrt(dx * dx + dy * dy); return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; } /***** Elliptical arcs *****/    

Vous pouvez faire la courbe comme ceci:

  //make a curve object var curves = {}; function getCurveFactor(d){ var factor = 0.3;//you may change this as per your choice. //make a key var key = d.source.index + "---"+ d.target.index; //see if the key is present in the object if (curves[key]){ //if key is present you need a bigger curve //so that it does not overlap curves[key] = curves[key] + factor; } else { //no key present keep the curve simple curves[key] = 1; } return curves[key]; } 

Cette fonction crée l’arc:

  function arcPath(d) { var x1 = d.target.x, y1 = d.target.y, x2 = d.source.x, y2 = d.source.y, dx = x2 - x1, dy = y2 - y1, dr = Math.sqrt(dx * dx + dy * dy), drx = dr, dry = dr; //store the curve factor inside the data. if(!d.curve){ d.curve = getCurveFactor(d); } return "M" + x1 + "," + y1 + "A" + (drx/d.curve) + ", " + (dry) + " " + 0 + ", " + 0 + ", " + 0 + " " + x2 + "," + y2; } 

code de travail ici