共计 11857 个字符,预计需要花费 30 分钟才能阅读完成。
D3
D3 or D3.js 代表 “Data Driven Documents”
选中、增加元素
select()
办法从文档中抉择一个元素,它接管指标元素的名称作为参数并返回第一个匹配该名称 HTML 节点。举例:
const anchor = d3.select('a');
append()
办法接管增加到文档中的元素,它会把该元素增加到一个选中的 HTML 节点,而后返回对该节点的援用。
text()
办法能够设置被选中节点的文本也能够失去以后文本。若是设置文本,须要将字符串作为参数传递。
D3 容许办法的嵌套。
上面是一个选中无序列表,并增加一个 list 元素的办法:
d3.select("ul")
.append("li")
.text("very important")
选中一组元素
应用 selectAll()
选中一组元素。它返回一个 HTML 节点数组。
上面是一个选中所有超链接元素的例子:
const anchors = d3.selectAll("a");
例子:
d3.selectAll("li")
.text("list item")
应用数据
首先应用 data()
办法去抉择 DOM 元素来和数据分割在一起。数据集作为参数传给该办法。
应用 enter()
办法为数据集中每一块元素创立一个新的 DOM 元素。
上面的例子是抉择 ul 元素并依据数组创立列表。
const dataset = ["a", "b", "c"];
d3.select("ul").selectAll("li")
.data(dataset)
.enter()
.append("li")
.text("New Item");
应用动态数据
text()
办法能够接管字符串或者回调函数作为参数。
selection.text((d) => d)
在下面的这个办法中,参数 d
指的是该数据集的一个入口。
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
// Add your code below this line
.text((d) => d + "USD");
// Add your code above this line
</script>
</body>
/*
12 USD
31 USD
22 USD
17 USD
25 USD
18 USD
29 USD
14 USD
9 USD
*/
给元素加内联款式
应用 style()
各动静元素增加款式。该办法接管一个以逗号 ,
分隔的键值对作为参数。
上面是一个把选中文本设置为蓝色的例子:
selection.style("color","blue");
设置选中字体:
d3.select("body")
.style("font-family","verdana");
基于数据改变款式
在 style()
中同样能够应用回调函数来改变不同元素的款式。应用参数 d
来代表数据点。
上面的例子是把数据集中小于 20 的元素设置为红色,其它设置为绿色。
d3.selectAll("h2")
.style("color", (d) => {if (d < 20) {return "red";} else return "green";
});
增加 class 属性
attr()
办法和 style()
办法相似,他接管以逗号宰割的值,并且能够应用回调函数。
上面是一个给元素增加 container class 的例子。
selection.attr("class", "container");
动静批改元素的高度
联合下面所学创立一个条形图 (bar chart)。
<style>
.bar {
width: 25px;
height: 100px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", (d) => d + "px");
</script>
</body>
扭转条形图的展现
<style>
.bar {
width: 25px;
height: 100px;
/* Add your code below this line */
marign: 2px;
/* Add your code above this line */
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", (d) => (d*10 + "px")) // Change this line
</script>
</body>
SVG in d3
SVG 的全称是:Scalable Vector Graphics。
scalable 的意思是对物体放大或者放大不会使物体马赛克(pixelated)。
SVG 在 HTML 中应用 svg
标签实现。
上面是一个创立 SVG 的例子:
<style>
svg {background-color: pink;}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 1
00;
const svg = d3.select("body")
// Add your code below this line
svg.append("svg").attr("width",w).attr("height",h);
// Add your code above this line
</script>
</body>
SVG 形态
SVG 反对多种数量的形态,例如:应用 <rect>
来示意矩形。
当把一个形态放入 SVG 区域时,能够设置 x,y 坐标系。原点(0,0)示意左上角。x 的正值会使图形向右挪动,y 的正值向上挪动。例如:把一个形态放在 500 宽,100 高的地位须要设置 x = 250,y = 50。
对于 <rect>
来说,它有四个属性,别离是高度、宽度和 x,y。该元素必须增加到 svg 节点,而不是 body 节点。
上面的例子是设置一个矩形
<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)
// Add your code below this line
svg.append("rect")
.attr("width", 25)
.attr("height", 100)
.attr("x", 0)
.attr("y", 0);
// Add your code above this line
</script>
</body>
对数据集中的每一个数据点创立一个 bar
<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")
// Add your code below this line
.data(dataset)
.enter()
.append("rect")
// Add your code above this line
.attr("x", 0)
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
对每个 bar 动静设置坐标
条形图的 y 坐标应该是统一的,而 x 坐标应该有所不同。通过设置 attr()
的回调函数来动静设置。回调函数接管两个参数,第一个用 d 代表数据点自身,第二个代表数据点在数组中的索引。格局:
selection.attr("property", (d,i) => {})
注:不须要应用 for 或者 forEach() 循环。
上面是扩充 30 倍的例子:
<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) => {
// Add your code below this line
return i*30;
// Add your code above this line
})
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
动静扭转高度
实际上就是批改数据点
<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", 0)
.attr("width", 25)
.attr("height", (d, i) => {
// Add your code below this line
return d * 3;
// Add your code above this line
});
</script>
</body>
倒置 SVG 元素
y
坐标也就是 y = heightOfSVG - heightOfBar
会把 bar 置于右上侧。
个别公式:y = h - m * d
,其中 m 是数据点 scale 的常量。
<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) => {
// Add your code below this line
return 100 - 3 * d;
// Add your code above this line
})
.attr("width", 25)
.attr("height", (d, i) => 3 * d);
</script>
</body>
扭转 SVG 图片的色彩
在 SVG 中,rect
形态应用 fill
来管制色彩。
上面设置色彩为海军蓝。
<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)
// Add your code below this line
.attr("fill", "navy");
// Add your code above this line
</script>
</body>
加标签
应用 SVG 的 text
给元素加标签。该属性同样具备 x 和 y 属性。
<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");
svg.selectAll("text")
.data(dataset)
.enter()
// Add your code below this line
.append("text")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d - 3)
.text((d, i) => d);
// Add your code above this line
</script>
<body>
给标签加款式
<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) => d * 3)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3)
// Add your code below this line
.attr("fill","red")
.style("font-size", "25px")
// Add your code above this line
</script>
</body>
给元素增加 hover 成果
<style>
.bar:hover {fill: brown;}
</style>
<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")
// Add your code below this line
.attr("class", "bar")
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3);
</script>
</body>
给元素增加 tooltip
当用户 hover 在一个元素上,tooltip 能够展现更多的信息。
应用 SVG 的 title
给元素增加 tooltip。应用 title
配合 text()
办法给条动静增加数据。
上面是一个例子:
<style>
.bar:hover {fill: brown;}
</style>
<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) => d * 3)
.attr("fill", "navy")
.attr("class", "bar")
// Add your code below this line
.append("title")
.text((d) => {return d;})
// Add your code above this line
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>
应用 SVG 环形创立 scatterplot
scatterplot 是另一种可视化的类型。它应用圆环来遍历数据点,每个数据点有两个值。这些值和 x、y 坐标绑定,用来定位圆环的地位。
SVG 的 circle
标签创立圆形。
上面是一个圆形的例子:
<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")
// Add your code below this line
.data(dataset)
.enter()
.append("circle");
// Add your code above this line
</script>
</body>
给圆形增加属性
圆形次要有三个属性。cx
和 cy
属性是坐标系。r
属性规定圆形的半径。
这三个属性能够应用一个回调函数动静设置它们的值。记住,所有在 data(dataset)
链后的办法会对每个数据项运行一次。回调函数中的 d
示意以后数据汇合中的数据项。能够应用括号表示法去失去数据集中的元素,如:d[0]
。
上面是一个例子:
<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")
// Add your code below this line
.attr("cx", (d) => d[0])
.attr("cy", (d) => h - d[1])
.attr("r", 5)
// Add your code above this line
</script>
</body>
给 scatterplot 增加标签
<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")
// Add your code below this line
.attr("x", (d) => d[0] + 5)
.attr("y", (d) => h - d[1])
.text((d) => (d[0] + "," + d[1]))
// Add your code above this line
</script>
</body>
创立线性 scale
scales
是一种函数,能够把数据集的数据映射为 SVG 画布。
例子:
const scale = d3.scaleLinear();
默认状况,scale 应用实体关系。输出和输入的后果雷同。
<body>
<script>
// Add your code below this line
const scale = d3.scaleLinear(); // Create the scale here
const output = scale(50); // Call scale with an argument here
// Add your code above this line
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
给 scale 设置 domain 和 range
如果一个数据集范畴从 50 – 480,这是输出的范畴,也叫 domain。
而后打算把这些数据点映射到 x 轴上,从 10 units 到 500 units,这就是输入的范畴,也叫 range。
domian()
和 range()
办法为 scale 设置这些值。这两个办法接管一个至多蕴含两个元素数组作为参数。例如:
scale.domain([50, 480]);
scale.range([50, 480]);
scale(40);
d3.scaleLinear();
最小的 domain 是 50 映射到最小的 range 为 10。
例子:
<body>
<script>
// Add your code below this line
const scale = d3.scaleLinear();
scale.domain([250, 500]).range([10, 150]);
// Add your code above this line
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
应用 d3.max 和 d3.min 办法找出数据集的最大和最小元素
例子:
const exampleData = [3, 45, 10, 9];
d3.min(exampleData);
d3.max(exampleData);
有些时候数据集是嵌套的,这样的状况下,须要给这两个函数传入回调函数。这时,参数 d
代表以后外部的数组。
const locationData = [[1, 7],[6, 3],[8, 3]];
const minX = d3.min(locationData, (d) => d[0]);
// minX = 1;
<body>
<script>
const positionData = [[1, 7, -4],[6, 3, 8],[2, 9, 3]]
// Add your code below this line
const output = d3.max(positionData, (d) => d[2]); // Change this line
// Add your code above this line
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
// output = 8;
应用动静 scale
<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;
// Padding between the SVG canvas boundary and the plot
const padding = 30;
// Create an x and y scale
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
// Add your code below this line
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
// Add your code above this line
const output = yScale(411); // Returns 30
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
应用预约义的 scale 搁置元素
<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>
退出 Axes
axisLeft()
和 axisBottom()
办法,去渲染 x 轴和 y 轴,绝对的,依据 xScale 创立 xAxis
const xAxis = d3.axisBottom(xScale);
下一步就是渲染
svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);