文章目录
Data-Driven Documents理解
首先它是js,js本质就是dom(Document Object Model,简称DOM)的增删查改,dom的本质就是一棵树,d3本质也是对一棵树进行操作。
selections
对dom操作,最开始就是定位,也就是选择哪一块,哪一颗子树
d3.selectAll("p").style("color", "blue");
selections操作
// Update…
var p = d3.select("body")
.selectAll("p")
.data([4, 8, 15, 16, 23, 42])
.text(function(d) { return d; });
// Enter…
p.enter().append("p")
.text(function(d) { return d; });
// Exit…
p.exit().remove();
直接上码:
导入库,这里使用d3.v3,d3.v5可能有差异:
<script src="http://d3js.org/d3.v3.min.js"></script>
建立画布,并把画布svg添加到html的body或者div里
var width = 960,
height = 960
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
建立力矩图
var force = d3.layout.force()
.gravity(.05)
.charge(-240)
.linkDistance(160)
.size([width, height]);
读取json数据
d3.json("graph.json", function(error, json) {
if (error) throw error;
}
把数据放进force里,force就可以直接使用自己的数据了
force.nodes(json.nodes)
.links(json.links)
.start();
依次把边添加到svg
selectAll(".link")相当于占位符,添加"line"标签,设置该line标签的属性
var link = svg.selectAll(".link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
依次把节点添加到svg
节点包括node和text两部分,使用group包起来,先添加g标签再添加circle和text标签
var node = svg.selectAll(".node")
.data(json.nodes)
.enter().append('g')
.attr("class", "node")
.style("fill","red")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.call(force.drag);
node.append("circle")
.attr("r", 8);
node.append("text")
.attr("dy", ".35em")
.text(function(d) { return d.name; });
定义事件 mouseover, mouseout
mouseover, mouseout为基本事件
transition变换过渡效果
function mouseover() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 80);
}
function mouseout() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 8);
}
定义事件 tick
实际就是补充div的属性
force.on("tick", tick);
function tick() {
link.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; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
};
拖拽固定
相当于重写了drag函数
var node_drag = d3.behavior.drag()
.on("dragstart", dragstart)
.on("drag", dragmove)
.on("dragend", dragend);
var node = svg.selectAll(".node")
.data(json.nodes)
.enter().append('g')
.attr("class", "node")
.style("fill","red")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
//.call(force.drag);
.call(node_drag);
function dragstart(d, i) {
force.stop() // stops the force auto positioning before you start dragging
}
function dragmove(d, i) {
d.px += d3.event.dx;
d.py += d3.event.dy;
d.x += d3.event.dx;
d.y += d3.event.dy;
tick(); // this is the key to make it work together with updating both px,py,x,y on d !
}
function dragend(d, i) {
d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
tick();
force.resume();
}
zoom
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")")
.call(zoom);
//specify what to do when zoom event listener is triggered
function zoomed() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
完整code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.link {
stroke: #777;
stroke-opacity: 0.5;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
d3.json("graph.json", function(error, json) {
if (error) throw error;
var margin = {top: -5, right: -5, bottom: -5, left: -5},
width = 960 - margin.left - margin.right,
height = 960 - margin.top - margin.bottom;
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")")
.call(zoom);
var force = d3.layout.force()
.gravity(.05)
.charge(-240)
.linkDistance(160)
.size([width, height]);
force.nodes(json.nodes)
.links(json.links)
.start();
var g = svg.append("g")
.attr("class", "everything");
var link = g.append("g")
.attr("class", "links")
.selectAll(".link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
// var node_drag = d3.behavior.drag()
// .on("dragstart", dragstart)
// .on("drag", dragmove)
// .on("dragend", dragend);
var node = g.append("g")
.attr("class", "nodes")
.selectAll(".node")
.data(json.nodes)
.enter().append('g')
.attr("class", "node")
.style("fill","red")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.call(force.drag);
//.call(node_drag);
node.append("circle")
.attr("r", 8);
node.append("text")
.attr("dy", ".35em")
.text(function(d) { return d.name; });
force.on("tick", tick);
function tick() {
link.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; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
};
function mouseover() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 80);
}
function mouseout() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 8);
}
// function dragstart(d, i) {
// force.stop() // stops the force auto positioning before you start dragging
// }
//
// function dragmove(d, i) {
// d.px += d3.event.dx;
// d.py += d3.event.dy;
// d.x += d3.event.dx;
// d.y += d3.event.dy;
// tick(); // this is the key to make it work together with updating both px,py,x,y on d !
// }
//
// function dragend(d, i) {
// d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
// tick();
// force.resume();
// }
//specify what to do when zoom event listener is triggered
function zoomed() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
});
</script>