【D3.js数据可视化系列教程】(十七)--通过键联结数据
2013-11-02 19:48
716 查看
最后效果:点击删除会从左侧消失。数值和条是对应的,即添加一条时更新位置后对应条上的数值还在这条上。
![](http://img.blog.csdn.net/20150119220103129?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGlhbnh1emhhbmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1. 键值对数据集
var dataset = [ {key:0,value:5}, {key:1,value:10}, {key:2,value:13}, {key:3,value:19}, {key:4,value:21}, {key:5,value:25}, {key:6,value:22}, {key:7,value:18}, {key:8,value:15}, {key:9,value:13}, ... ];
2. 更新数据引用,包含下面所有关于要使用到d.value的地方
.domain([0,d3.max(dataset,function(d){ return d.value; })]) .range([0,h]);
3. 定义键函数(简洁),以备数据绑定到元素的时候使用
var key=function(d){ return d.key; };
4. 从左侧退出
bars.exit().transition().duration(500) .attr("x", -xScale.rangeBand())//w-xScale.rangeBand()间隙宽其实其他负数也行 .remove();});
5. 实现键联结数据
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>testD3-18-update.html</title> <script type="text/javascript" src="http://localhost:8080/spring/js/d3.v3.js"></script> <style type="text/css"> /* 鼠标悬停时变色*/ rect:hover{ fill :orange; } /* 过渡效果*/ rect{ -moz-transiton:all 0.3s; -o-transiton:all 0.3s; -webkit-transition:all 0.3s; transition:all 0.3s } /*(2)给提示条加上样式*/ #tooltip { position: absolute; width: 200px; height: auto; padding: 10px; background-color: white; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); pointer-events: none; } #tooltip.hidden { display: none; } #tooltip p { margin: 0; font-family: sans-serif; font-size: 16px; line-height: 20px; } </style> </head> <body> <button>单击更新</button> <br> <p id="remove" class="click">单击删除</p><div id="add" class="click">单击添加</div> <br> <!-- (1)创建div提示层 --> <div id="tooltip" class="hildden"> <p><strong>提示:</strong></p> <p><span id="value">100</span>%</p> </div> <br> <script type="text/javascript"> //键值对数据集 var dataset = [ { key : 0, value : 5 }, { key : 1, value : 10 }, { key : 2, value : 13 }, { key : 3, value : 19 }, { key : 4, value : 21 }, { key : 5, value : 25 }, { key : 6, value : 22 }, { key : 7, value : 18 }, { key : 8, value : 15 }, { key : 9, value : 13 }, { key : 10, value : 11 }, { key : 11, value : 12 }, { key : 12, value : 15 }, { key : 13, value : 20 }, { key : 14, value : 18 }, { key : 15, value : 17 }, { key : 16, value : 16 }, { key : 17, value : 18 }, { key : 18, value : 23 }, { key : 19, value : 25 } ]; //设置SVG的高宽 var w = 600; var h = 250; var barPadding = 1; //定义序数比例尺 var xScale = d3.scale.ordinal()//序数比例尺 .domain(d3.range(dataset.length)) .rangeRoundBands([ 0, w ], 0.05); // 更新数据引用,包含下面所有关于要使用到d.value的地方 var yScale = d3.scale.linear()//y仍然是线性比例尺 .domain([ 0, d3.max(dataset, function(d) {return d.value;}) ]) .range([ 0, h ]); // 定义键函数(简洁),以备数据绑定到元素的时候使用 //把所有.data(dataset)改成.data(dataset,key) var key = function(d) { return d.key; }; //值函数 var value = function(d) { return d.value; }; //条排序函数 var sortOrders = false; var sortBars = function() { sortOrders = !sortOrders;//(3)每点击一次排序方向改变 svg.selectAll("rect") .sort(function(a, b) { if (sortOrders) { //对数据集升序排序 return d3.ascending(a.value, b.value);//这个地方注意是键值对所以要加上值的引用b.value } else { //对数据集降序排序 return d3.descending(a.value, b.value); } }) .transition() .duration(1000) .attr("x", function(d, i) {//对排序之后的横坐标重排 return xScale(i); }); svg.selectAll("text") .sort(function(a, b) { if (sortOrders) { //对数据集升序排序 return d3.ascending(a.value, b.value);//这个地方注意是键值对所以要加上值的引用b.value } else { //对数据集降序排序 return d3.descending(a.value, b.value); } }) .transition() .duration(1000) .attr("x", function(d, i) {//对排序之后的横坐标重排 return xScale(i)+ xScale.rangeBand() / 2; }); }; d3.select("#tooltip").classed("hidden", true); //创建SVG元素 var svg = d3.select("body")//选中DOM中的目标元素 .append("svg")//为目标元素附加上一个svg子元素 .attr("width", w)//设置这个svg的宽 .attr("height", h);//设置这个svg的高 //为SVG添加条形 svg.selectAll("rect")//选中空元素,表示即将创建这样的元素 .data(dataset, key)//对此后的方法都执行dataset.length遍 .enter()//数据元素值比前面选中的DOM元素多就创建一个新的DOM元素 .append("rect")//取得enter的占位元素,并把rect追加到对应的DOM中 .attr("x", function(d, i) {//设置横坐标,从0开始每次右移元素宽那么长(w / dataset.length) //return i * (w / dataset.length); return xScale(i);//这里使用序数比例尺,自己去找刚才划分好的档位 }).attr("y", function(d) {//设置纵坐标,纵坐标正方向是从上往下的,所以条有多长就要设置起点是相对于h再向上移动条长 return h - yScale(d.value); }) //.attr("width", w / dataset.length - barPadding)//设置元素宽,留出间隙宽barPadding。 .attr("width", xScale.rangeBand())//这里xScale比例尺已经设置间距了所以直接用 .attr("height", function(d) { return yScale(d.value); }).attr("fill", function(d) {//设置RGB颜色与数值的关系 return "rgb(0, 0, " + (d.value * 10) + ")"; }) //点击排序 .on("click", function() { sortBars(); }) //(3)更新提示条的值和位置 .on("mouseover",function(d) { //取得提示显示的位置 var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.rangeBand() / 2; var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + h / 2; d3.select("#tooltip") .style("left", xPosition + "px") .style("top", yPosition + "px") .select("#value") .text(d.value); d3.select("#tooltip").classed("hidden", false); }) //移除提示条 .on("mouseout", function() { //(4)添加隐藏类 d3.select("#tooltip").classed("hidden", true);//ID 选择的语法:"#tooltip" }); //为条加上数值 svg.selectAll("text").data(dataset, key).enter().append("text") .text(function(d) { return d.value; }) .attr("text-anchor", "middle").attr("x", function(d, i) { return xScale(i) + xScale.rangeBand() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; }) .attr("font-family", "sans-serif") .attr("font-size",function(d) { return xScale.rangeBand() / 2; }) .attr("fill", "white"); //删除一条、添加一条 d3.selectAll(".click") .on("click",function() { //根据ID确定点击的是哪个标签 var paragraphID = d3.select(this).attr("id"); //添加删除组合起来 if (paragraphID == "add") { //数据集最后添加数值 var maxValue = 75; var newNumber = Math.floor(Math.random() * maxValue);//0-24的整数 //根据最后一个key添加一个值 var lastKeyValue = dataset[dataset.length - 1].key; dataset.push({ key : lastKeyValue + 1, value : newNumber }); //更新X轴比例尺 xScale.domain(d3.range(dataset.length)); //选择所有条 var bars = svg.selectAll("rect").data(dataset, key); //绑定数据到元素集,返回更新的元素集 var texts = svg.selectAll("text").data(dataset, key); //添加条形元素到最右边 bars.enter().append("rect").attr("x", w);//在SVG最右边,不可见 texts.enter().append("text"); //更新新矩形到可见范围内 //并在这个时候根据数据集为每个条设置对应的属性 bars.transition() .duration(500) .attr("x",function(d, i) { return xScale(i); })//每个X对应到它相应的档位上 .attr("y", function(d) { return h - yScale(d.value); }).attr("width", xScale.rangeBand())//这里xScale比例尺已经设置间距了所以直接用 .attr("height", function(d) { return yScale(d.value); }).attr("fill",function(d) {//设置RGB颜色与数值的关系 return "rgb(0, 0, " + (d.value * 10) + ")"; }); texts.transition() .text(function(d) { return d.value; }) .attr("text-anchor", "middle") .attr("x",function(d, i) { return xScale(i)+ xScale.rangeBand()/ 2; }) .attr("y",function(d) {return h- yScale(d.value)+ 14;}) .attr("font-family", "sans-serif") .attr("font-size", "12px") .attr("fill", "red"); } else { //删除的操作 //选择所有条 dataset.shift(); //更新X轴比例尺 xScale.domain(d3.range(dataset.length)); var bars = svg.selectAll("rect").data(dataset, key); var texts = svg.selectAll("text").data(dataset, key); //从左侧退出 bars.exit().transition().duration(500) .attr("x", -xScale.rangeBand())//w-xScale.rangeBand()间隙宽其实其他负数也行 .remove(); //从左侧退出 texts.exit().transition().duration(500) .attr("x", -xScale.rangeBand())//w-xScale.rangeBand()间隙宽其实其他负数也行 .remove(); } }); // 更新条形数长短的代码,需要一个button标签配合 //特别注意:这里选中的元素必须在d3选择器之前,或许要先加载完了元素才能被选中 d3.select("button").on("click",function() { // 新数据集,随机数组 var numValues = dataset.length; dataset = []; var maxValue = 75; var newNumber; for ( var i = 0; i < numValues; i++) { newNumber = Math.floor(Math.random() * maxValue);//0-24的整数 //根据i添加一个值 dataset.push({ key : i, value : newNumber }); } // 更新比例尺,免使纵坐标超出范围 yScale.domain([ 0, d3.max(dataset, value) ]);//只要更新定义域就行了,映射到的值域不变 //更新所有的矩形 svg.selectAll("rect").data(dataset, key).transition()// 加上过渡动画 .delay(function(d, i) { return i / dataset.length * 1000; })//指定过度什么时间开始,可以用函数控制每一条的动画时间,这样就可得到钢琴版的效果 .duration(2000)// 加上动画的持续时间,以毫秒计算 .ease("linear")// 缓动函数:有circle(加速)elastic(伸缩),linear(匀速),bounce(弹跳) .attr("y", function(d) { return h - yScale(d.value); }).attr("height", function(d) { return yScale(d.value); }); // 更新条上的数值 svg.selectAll("text") .data(dataset, key) .text(function(d) { return d.value; }) .attr("text-anchor", "middle") .attr("x",function(d, i) { return xScale(i) + xScale.rangeBand() / 2; }) .attr("y", function(d) { return h - yScale(d.value) + 14; }) .attr("font-family", "sans-serif").attr("font-size","12px") .attr("fill", "red"); }); </script> </body> </html>
相关文章推荐
- 【D3.js数据可视化系列教程】--(四)使用数据
- 【D3.js数据可视化系列教程】--(六)生成测试数据
- 【D3.js数据可视化系列教程】--(三)数据绑定
- 【D3.js数据可视化系列教程】--(九)D3的数据类型
- 【D3.js数据可视化系列教程】(十六)--更新、过度和动画
- 【D3.js数据可视化系列教程】(十九)--交互图表之鼠标悬停
- 【D3.js数据可视化系列教程】(二十八)--弦图
- 【D3.js数据可视化系列教程】(二十九)--折叠树
- 【D3.js数据可视化系列教程】(三十一)-- 力导向图之分子式
- 【D3.js数据可视化系列教程】(三十四)-- sankey图
- 【D3.js数据可视化系列教程】(三十五)-- 矩形树
- WPF入门教程系列十七——WPF中的数据绑定(三)
- WPF入门教程系列十七——WPF中的数据绑定(三)
- 【D3.js数据可视化系列教程】(二十)--交互图表之条形图排序
- 【D3.js数据可视化系列教程】--(二)最简单的开始:添加元素
- 【D3.js数据可视化系列教程】(二十二)--交互图表之提示条
- 【D3.js数据可视化系列教程】--(十五)SVG基本图形绘制
- 【D3.V3.js数据可视化系列教程】--(六)数据的威力
- 【D3.js数据可视化系列教程】--(五)用层画条形图
- 【D3.js数据可视化系列教程】(二十六)--加载SVG文件