【发布时间】:2026-01-26 06:40:01
【问题描述】:
我正在使用强制布局来创建有向图。 它呈现在画布上。我的示例位于http://jsbin.com/vuyapibaqa/1/edit?html,output
现在我的灵感来自
https://bl.ocks.org/mattkohl/146d301c0fc20d89d85880df537de7b0#index.html
d3 svg 中的资源很少,我试图在画布中获得类似的东西。
http://jsfiddle.net/zhanghuancs/a2QpA/
http://bl.ocks.org/mbostock/1153292https://bl.ocks.org/ramtob/3658a11845a89c4742d62d32afce3160
http://bl.ocks.org/thomasdobber/9b78824119136778052f64a967c070e0
Drawing multiple edges between two nodes with d3.
想用箭头添加椭圆弧连接边。如何在画布中实现这一点。
我的代码:
<!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>
【问题讨论】:
-
这可能会有所帮助:"Draw path in Canvas with SVG Path data (SVG paths to Canvas paths)"。这使得绘制线条非常容易。不过,您仍然需要弄清楚如何绘制标记。
-
我试过了,没用,你能帮忙吗?
-
我 forked 你的 JSBin 并添加了椭圆弧,这非常简单(查找
/***** Elliptical arcs *****/cmets)。当我第一次阅读您的问题时,我已经开始将其放入答案中,但是一旦我意识到箭头标记丢失,我就不再发布它。如果你也想要它们,这将是一个更加复杂的壮举。 -
类似这样的东西,我们可以把它转换成画布吗?
标签: javascript jquery html d3.js canvas