D3.js - 工作示例
让我们在本章中制作一个动画条形图。对于此示例,我们将上一章人口记录中使用的 data.csv 文件作为数据集并生成一个动画条形图。
为此,我们需要执行以下步骤 −
步骤 1 − 应用样式 − 使用下面给出的编码应用 CSS 样式。
<style> .bar { fill: green; } .highlight { fill: red; } .title { fill: blue; font-weight: bold; } </style>
步骤 2 − 定义变量 − 让我们使用下面的脚本定义 SVG 属性。
<script> var svg = d3.select("svg"), margin = 200, width = svg.attr("width") - margin, height = svg.attr("height") - margin; </script>
步骤 3 − 附加文本 −现在,使用下面的代码添加文本并应用转换。
svg.append("text") .attr("transform", "translate(100,0)") .attr("x", 50) .attr("y", 50) .attr("font-size", "20px") .attr("class", "title") .text("Population bar chart")
步骤 4 − 创建比例范围 − 在此步骤中,我们可以创建比例范围并添加组元素。它定义如下。
var x = d3.scaleBand().range([0, width]).padding(0.4), y = d3.scaleLinear() .range([height, 0]); var g = svg.append("g") .attr("transform", "translate(" + 100 + "," + 100 + ")");
步骤 5 − 读取数据 − 我们已经在前面的示例中创建了 data.csv 文件。我们在这里使用了同一个文件。
year,population 2006,40 2008,45 2010,48 2012,51 2014,53 2016,57 2017,62
现在,使用下面的代码读取上述文件。
d3.csv("data.csv", function(error, data) { if (error) { throw error; }
步骤 6 − 设置域 − 现在,使用下面的代码设置域。
x.domain(data.map(function(d) { return d.year; })); y.domain([0, d3.max(data, function(d) { return d.population; })]);
步骤 7 − 添加 X 轴 − 现在,您可以将 X 轴添加到转换中。如下所示。
g.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)).append("text") .attr("y", height - 250).attr("x", width - 100) .attr("text-anchor", "end").attr("font-size", "18px") .attr("stroke", "blue").text("year");
步骤 8 − 添加 Y 轴 − 使用下面给出的代码将 Y 轴添加到转换中。
g.append("g") .append("text").attr("transform", "rotate(-90)") .attr("y", 6).attr("dy", "-5.1em") .attr("text-anchor", "end").attr("font-size", "18px") .attr("stroke", "blue").text("population");
步骤 9 − 附加组元素 − 现在,附加组元素并按照以下定义将变换应用于 Y 轴。
g.append("g") .attr("transform", "translate(0, 0)") .call(d3.axisLeft(y))
步骤 10 − 选择 bar 类 − 现在,按照以下定义选择 bar 类中的所有元素。
g.selectAll(".bar") .data(data).enter() .append("rect") .attr("class", "bar") .on("mouseover", onMouseOver) .on("mouseout", onMouseOut) .attr("x", function(d) { return x(d.year); }) .attr("y", function(d) { return y(d.population); }) .attr("width", x.bandwidth()) .transition() .ease(d3.easeLinear) .duration(200) .delay(function (d, i) { return i * 25; }) .attr("height", function(d) { return height - y(d.population); }); });
在这里,我们为 mouseout 和 mouseover 添加了监听器事件来执行动画。当鼠标悬停在特定栏上并移出时,它会应用动画。这些函数将在以下步骤中解释。
.ease(d3.easeLinear) 函数用于执行动画中的表观运动。它处理持续时间为 200 的慢进和慢出运动。可以使用 − 计算延迟
.delay(function (d, i) { return i * 25; })
步骤 11 − 鼠标悬停事件处理函数 − 让我们创建一个鼠标悬停事件处理程序来处理鼠标事件,如下所示。
function onMouseOver(d, i) { d3.select(this) .attr('class', 'highlight'); d3.select(this) .transition() .duration(200) .attr('width', x.bandwidth() + 5) .attr("y", function(d) { return y(d.population) - 10; }) .attr("height", function(d) { return height - y(d.population) + 10; }); g.append("text") .attr('class', 'val') .attr('x', function() { return x(d.year); }) .attr('y', function() { return y(d.value) - 10; }) }
在这里,在 mouseover 事件中,我们想要增加条形的宽度和高度,并将所选条形的条形颜色更改为红色。对于颜色,我们添加了一个类"highlight",它将所选条形的颜色更改为红色。
条形的过渡函数,持续时间为 200 毫秒。当我们将条形的宽度增加 5px,将高度增加 10px 时,从条形的先前宽度和高度到新宽度和高度的过渡将持续 200 毫秒。
接下来,我们为条形计算了一个新的"y"值,以便条形不会因新的高度值而扭曲。
步骤 12 − Mouseout 事件处理函数 − 让我们创建一个 mouseout 事件处理函数来处理鼠标事件。它定义如下。
function onMouseOut(d, i) { d3.select(this).attr('class', 'bar'); d3.select(this) .transition() .duration(400).attr('width', x.bandwidth()) .attr("y", function(d) { return y(d.population); }) .attr("height", function(d) { return height - y(d.population); }); d3.selectAll('.val') .remove() }
在这里,在 mouseout 事件中,我们想要删除在 mouseover 事件中应用的选择功能。因此,我们将 bar 类恢复为原始的"bar"类,并恢复所选栏的原始宽度和高度,并将 y 值恢复为原始值。
d3.selectAll('.val').remove() 函数用于删除我们在栏选择期间添加的文本值。
步骤 13 − 工作示例 − 完整的程序在以下代码块中给出。创建一个网页 animated_bar.html 并向其中添加以下更改。
<!DOCTYPE html> <html> <head> <style> .bar { fill: green; } .highlight { fill: red; } .title { fill: blue; font-weight: bold; } </style> <script src = "https://d3js.org/d3.v4.min.js"></script> <title> Animated bar chart </title> </head> <body> <svg width = "500" height = "500"></svg> <script> var svg = d3.select("svg"), margin = 200, width = svg.attr("width") - margin, height = svg.attr("height") - margin; svg.append("text") .attr("transform", "translate(100,0)") .attr("x", 50).attr("y", 50) .attr("font-size", "20px") .attr("class", "title") .text("Population bar chart") var x = d3.scaleBand().range([0, width]).padding(0.4), y = d3.scaleLinear().range([height, 0]); var g = svg.append("g") .attr("transform", "translate(" + 100 + "," + 100 + ")"); d3.csv("data.csv", function(error, data) { if (error) { throw error; } x.domain(data.map(function(d) { return d.year; })); y.domain([0, d3.max(data, function(d) { return d.population; })]); g.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)) .append("text") .attr("y", height - 250) .attr("x", width - 100) .attr("text-anchor", "end") .attr("font-size", "18px") .attr("stroke", "blue").text("year"); g.append("g") .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", "-5.1em") .attr("text-anchor", "end") .attr("font-size", "18px") .attr("stroke", "blue") .text("population"); g.append("g") .attr("transform", "translate(0, 0)") .call(d3.axisLeft(y)) g.selectAll(".bar") .data(data) .enter() .append("rect") .attr("class", "bar") .on("mouseover", onMouseOver) .on("mouseout", onMouseOut) .attr("x", function(d) { return x(d.year); }) .attr("y", function(d) { return y(d.population); }) .attr("width", x.bandwidth()).transition() .ease(d3.easeLinear).duration(200) .delay(function (d, i) { return i * 25; }) .attr("height", function(d) { return height - y(d.population); }); }); function onMouseOver(d, i) { d3.select(this) .attr('class', 'highlight'); d3.select(this) .transition() .duration(200) .attr('width', x.bandwidth() + 5) .attr("y", function(d) { return y(d.population) - 10; }) .attr("height", function(d) { return height - y(d.population) + 10; }); g.append("text") .attr('class', 'val') .attr('x', function() { return x(d.year); }) .attr('y', function() { return y(d.value) - 10; }) } function onMouseOut(d, i) { d3.select(this) .attr('class', 'bar'); d3.select(this) .transition() .duration(200) .attr('width', x.bandwidth()) .attr("y", function(d) { return y(d.population); }) .attr("height", function(d) { return height - y(d.population); }); d3.selectAll('.val') .remove() } </script> </body> </html>
现在,请求浏览器,我们将看到以下响应。
如果我们选择任何栏,它将以红色突出显示。D3 是一个通用可视化库,用于将数据转换为信息、文档、元素等,并最终帮助创建数据可视化。