I am using forced layout to create directed graph . Its rendered on canvas . My sample example is at http://jsbin.com/vuyapibaqa/1/edit?html,output
Now I am inspired from
https://bl.ocks.org/mattkohl/146d301c0fc20d89d85880df537de7b0#index.html
Few Resources in d3 svg , something similar i am trying to get in canvas.
http://jsfiddle.net/zhanghuancs/a2QpA/
http://bl.ocks.org/mbostock/1153292 https://bl.ocks.org/ramtob/3658a11845a89c4742d62d32afce3160
http://bl.ocks.org/thomasdobber/9b78824119136778052f64a967c070e0
Drawing multiple edges between two nodes with d3.
Want to add elliptical arc connecting edge with arrow . How to achieve this in canvas.
My Code :
<!DOCTYPE html>
<html>
<head>
<title>Sample Graph Rendring Using Canvas</title>
<script src="https://rawgit.com/gka/randomgraph.js/master/randomgraph.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
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(d.x, d.y);
var r = d3.select(this).select("circle").node().getAttribute('r');
d.x = Math.max(30, Math.min(width - 30, d.x));
d.y = Math.max(30, Math.min(height - 30, d.y));
context.closePath();
context.arc(d.x, d.y, r, 0, 2 * Math.PI);
context.fillStyle = d3.select(this).select("circle").node().getAttribute('fill');
context.strokeStyle = d3.select(this).select("circle").node().getAttribute('strokeStyle');
context.stroke();
context.fill();
context.beginPath();
context.arc(d.x + 15, d.y-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),d.x + 10, d.y-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 *****/
</script>
</body>
</html>