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 USD31 USD22 USD17 USD25 USD18 USD29 USD14 USD9 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 linesvg.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 linereturn 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 linereturn 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 linereturn 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>

给圆形增加属性

圆形次要有三个属性。cxcy 属性是坐标系。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);