官方网站:https://d3js.org/
示例
d3.js 力布局
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<title>d3-force</title>
<link rel="shortcut icon" href="favicon.ico" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
/>
<style>
.svg {
user-select: none;
}
</style>
<script src="js/d3.js"></script>
</head>
<body>
<svg class="svg" width="1200" height="650"></svg>
<script>
const svg = d3.select("svg");
const height = +svg.attr("height");
const width = +svg.attr("width");
const margin = {
top: 150,
left: 50,
right: 50,
bottom: 0,
};
const innerHeight = height - margin.top - margin.bottom;
const innerWidth = width - margin.left - margin.right;
var color = d3.scaleOrdinal(d3.schemeCategory10);
let link;
let nodes;
let simulation;
const render_init = function () {
svg
.append("text")
.attr("class", "title")
.attr("font-size", "2em")
.attr("x", margin.left)
.attr("y", margin.top / 2)
.attr("transform", `translate(0,-40)`)
.attr("font-weight", "bold")
.attr("fill", "blue")
.html("Force Simulation");
svg
.append("g")
.attr("id", "maingroup")
.attr("x", margin.left)
.attr("y", margin.top)
.attr("transform", `translate(${margin.left},${margin.top})`)
.attr("width", innerWidth)
.attr("height", innerHeight);
};
const tick = function () {
link
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
nodes.attr("transform", (d) => `translate(${d.x},${d.y})`);
};
const dragstarted = function (event, d) {
if (!event.active) {
// 设置衰减系数,对节点位置移动过程的模拟,数值越高移动越快,数值范围[0,1]
simulation.alphaTarget(0.3).restart();
d.x = event.x;
d.y = event.y;
}
};
const dragged = function (event, d) {
d.x = event.x;
d.y = event.y;
};
const dragended = function (event, d) {
if (!d3.active) {
simulation.alphaTarget(0);
}
//让它回到原来的位置
// d.x = null;
// d.y = null;
};
d3.json("./data/miserables.json").then((data) => {
data.nodes.forEach((node, index) => {
node.id = index;
});
render_init();
const group = d3.select("#maingroup");
simulation = d3
.forceSimulation()
.nodes(data.nodes)
.force("manyBody", d3.forceManyBody())
.force("center", d3.forceCenter(innerWidth / 2, innerHeight / 2))
.force(
"link",
d3.forceLink(data.links).id((d) => d.id)
)
.force("collide", d3.forceCollide(20))
.on("tick", tick);
//注意设置stroke
link = group
.append("g")
.attr("class", "linkgroup")
.selectAll("line")
.data(data.links)
.enter()
.append("line")
.attr("stroke-width", (d) => Math.sqrt(d.value))
.attr("stroke", "green")
.attr("stroke-opacity", 0.6);
nodes = group
.append("g")
.attr("class", "nodegroup")
.selectAll(".node")
.data(data.nodes)
.join("g")
.attr("class", "node");
var circle = nodes
.append("circle")
.attr("r", 8)
.attr("fill", (d) => color(d.group));
var label = nodes
.append("text")
.attr("x", 6)
.attr("y", 3)
.html((d) => d.id)
.attr("font-size", "12px");
const dragFunc = d3
.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
dragFunc(nodes); //拖曳对象
});
</script>
</body>
</html>
效果图