本文介绍了使用d3画布强制定向图多边的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我创建了具有多个边缘的强制有向图,但是在仅仅显示它之后,其他的重叠在一起。我想创建像
I have created forced directed graph which has multiple edges , but after rending it shows only , other one overlaps on one another . I want to create something like https://bl.ocks.org/mattkohl/146d301c0fc20d89d85880df537de7b0#index.html
我的代码:
<!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>
推荐答案
你可以像这样制作曲线:
You can make the curve like this:
//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];
}
此函数生成弧:
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;
}
工作代码
这篇关于使用d3画布强制定向图多边的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!