console
var marge = { top: 60, bottom: 60, left: 60, right: 60 }
var svg = d3.select("svg")
var width = svg.attr("width")
var height = svg.attr("height")
var g = svg.append("g")
.attr("transform", "translate(" + marge.top + "," + marge.left + ")");
var nodes = [
{ name: "顺哥哥" },
{ name: "李小姐" },
{ name: "龙师傅" },
{ name: "啊山" },
{ name: "社会罗" },
{ name: "虫子" },
{ name: "武松" },
{ name: "黔南三都" },
{ name: "毕节纳雍" },
{ name: "黔东南黎平" },
{ name: "毕节织金" },
{ name: "黔南都匀" },
{ name: "毕节威宁" },
{ name: "班长" },
{ name: "心理委员" },
{ name: "宣传委员" },
];
var edges = [
{ source: 0, target: 7, realtion: "籍贯", value: 1.3 },
{ source: 1, target: 8, realtion: "籍贯", value: 0.8 },
{ source: 2, target: 9, realtion: "籍贯", value: 1.3 },
{ source: 3, target: 10, realtion: "籍贯", value: 1.8 },
{ source: 4, target: 11, realtion: "籍贯", value: 0.5 },
{ source: 5, target: 12, realtion: "籍贯", value: 1.3 },
{ source: 0, target: 6, realtion: "老乡", value: 1 },
{ source: 0, target: 14, realtion: "职位", value: 1.3 },
{ source: 5, target: 13, realtion: "职位", value: 1.3 },
{ source: 3, target: 15, realtion: "职位", value: 1.3 },
{ source: 0, target: 1, realtion: "室友", value: 0.3 },
{ source: 0, target: 2, realtion: "室友", value: 1.3 },
{ source: 0, target: 3, realtion: "室友", value: 1.3 },
{ source: 0, target: 4, realtion: "室友", value: 0.6 },
{ source: 0, target: 5, realtion: "同学", value: 1.3 },
{ source: 1, target: 6, realtion: "基友", value: 3 },
];
var colorScale = d3.scaleOrdinal()
.domain(d3.range(nodes.length))
.range(d3.schemeCategory10);
var forceSimulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter());;
forceSimulation.nodes(nodes)
.on("tick", ticked);
forceSimulation.force("link")
.links(edges)
.distance(function (d) {
return d.value * 100;
})
forceSimulation.force("center")
.x(width / 2)
.y(height / 2);
console.log(nodes);
console.log(edges);
var links = g.append("g")
.selectAll("line")
.data(edges)
.enter()
.append("line")
.attr("stroke", function (d, i) {
return colorScale(i);
})
.attr("stroke-width", 1);
var linksText = g.append("g")
.selectAll("text")
.data(edges)
.enter()
.append("text")
.text(function (d) {
return d.realtion;
})
.style("font-size", 12)
var gs = g.selectAll(".circleText")
.data(nodes)
.enter()
.append("g")
.attr("transform", function (d, i) {
var cirX = d.x;
var cirY = d.y;
return "translate(" + cirX + "," + cirY + ")";
})
.call(d3.drag()
.on("start", started)
.on("drag", dragged)
.on("end", ended)
);
gs.append("circle")
.attr("r", 10)
.attr("fill", function (d, i) {
return colorScale(i);
})
gs.append("text")
.attr("x", -30)
.attr("y", -25)
.attr("dy", 10)
.text(function (d) {
return d.name;
})
function ticked() {
links
.attr("x1", function (d) { return d.source.x; })
.attr("y1", function (d) { return d.source.y; })
.attr("x2", function (d) { return d.target.x; })
.attr("y2", function (d) { return d.target.y; });
linksText
.attr("x", function (d) {
return (d.source.x + d.target.x) / 2;
})
.attr("y", function (d) {
return (d.source.y + d.target.y) / 2;
});
gs
.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });
}
function started(d) {
if (!d3.event.active) {
forceSimulation.alphaTarget(0.8).restart();
}
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function ended(d) {
if (!d3.event.active) {
forceSimulation.alphaTarget(0);
}
d.fx = null;
d.fy = null;
}
<h1>D3力导向图</h1>
<script src="https://d3js.org/d3.v5.min.js">
</script>
<svg width="960" height="600"></svg>