D3.js
1. 思维导图
2. 基础
2.1 select
选择一个DOM元素,const anchor = d3.select("a");
用法同document.querySelector()
2.2 selectAll
选择一组DOM元素,用法同document.querySelectorAll()
2.3 append
在选择的元素里添加新的DOM元素,返回新元素
2.4 text
返回结点文本或者设置结点文本,参数是字符串或者回调函数
d3.select("ul")
.append("li")
.text("Very important item");
2.5 data
将数据附加到选中的DOM元素
2.6 enter
为数据集中的每个数据创建一个新元素,当选中的DOM元素个数少于数据个数时,enter会创建缺少的元素
<body>
<ul></ul>
<script>
const dataset = ["a", "b", "c"];
d3.select("ul").selectAll("li")
.data(dataset)
.enter()
.append("li")
.text("New item");
</script>
</body>
此处enter方法检查数据集并运行后面的代码三次,也就是对数组中的每个项运行一次
2.7 style
style方法能添加行内css样式,参数是逗号分隔的键值对或回调函数
selection.style("property", (d, i) => {
/*
* d is the data point value
* i is the index of the data point in the array
*/
});
参数i
可以省略
2.8 attr
attr方法给元素添加html属性,包括class,用法同style
selection.attr("property", (d, i) => {
/*
* d is the data point value
* i is the index of the data point in the array
*/
})
参数i
可以省略
2.9 示例
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy");
</script>
<body>
3. 进阶
3.1 labels
使用svg的text节点向图标中添加标签
3.2 hover effect
使用attr方法和css的:hover
伪类实现悬停效果
3.3 tooltip
使用svg的title节点添加提示
SVG绘图中的每个窗口元素或图形元素都可以提供一个title描述性字符串,该描述只能是纯文本。如果当前的SVG文档片段在可视媒体中呈现为SVG,title元素不会呈现为绘图的一部分。然而,一些用户代理可能会,举个例子,把title显示为一个提示冒泡。
3.4 示例
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 200;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy")
.attr("class", "bar")
.append("title")
.text((d) => d)
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (d * 3 + 3))
</script>
</body>
3.5 scatter plot
使用svg的cicle节点画点
3.6 示例
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d, i) => d[0])
.attr("cy", (d, i) => h - d[1])
.attr("r", 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => "" + d[0] + ", " + d[1])
.attr("x", (d) => d[0] + 5)
.attr("y", (d) => h - d[1])
</script>
</body>
3.7 Scales
Scales函数将一组原始数据点映射到SVG画布的像素上
3.7.1 scaleLinear
scaleLinear用于定量数据
3.7.2 domain, range
domain 和 range 分别设置输入输出的数据范围
// Set a domain
// The domain covers the set of input values
scale.domain([50, 480]);
// Set a range
// The range covers the set of output values
scale.range([10, 500]);
scale(50) // Returns 10
scale(480) // Returns 500
scale(325) // Returns 323.37
scale(750) // Returns 807.67
3.7.3 min, max
min和max 分别找出数据集中的最小值和最大值
const exampleData = [34, 234, 73, 90, 6, 52];
d3.min(exampleData) // Returns 6
d3.max(exampleData) // Returns 234
const locationData = [[1, 7],[6, 3],[8, 3]];
// Returns the smallest number out of the first elements
const minX = d3.min(locationData, (d) => d[0]);// minX compared 1, 6, and 8 and is set to 1
3.8 示例
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d[0]))
.attr("cy", (d) => yScale(d[1]))
.attr("r", 5)
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + ", "+ d[1]))
.attr("x", (d) => xScale(d[0] + 10))
.attr("y", (d) => yScale(d[1]))
</script>
</body>
3.9 axes
axesLeft()
生成 y 轴
axesBottom()
生成 x 轴
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", "translate(0, " + (h - padding) + ")")
.call(xAxis);
3.10 示例
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d[0]))
.attr("cy",(d) => yScale(d[1]))
.attr("r", (d) => 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + "," + d[1]))
.attr("x", (d) => xScale(d[0] + 10))
.attr("y", (d) => yScale(d[1]))
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(" + padding +",0)")
.call(yAxis);
</script>
</body>