【D3.js数据可视化系列教程】(十八)--组合添加删除

原文链接:https://blog.csdn.net/zhang__tianxu/article/details/14086627

最后效果:

单击更新能实现像之前那样的更新了。

但是,单击添加和删除时,只能捕获第一个p标签,不能捕获第二个。

  1. 根据ID确定点击的是哪个标签

var paragraphID=d3.select(this).attr("id") ;

  2. 添加删除组合起来

if(paragraphID=="add"){

  3. 根据最后一个key添加一个值

  1. var lastKeyValue=dataset[dataset.length-1].key;
  2. dataset.push({
  3. key:lastKeyValue+1,
  4. value:newNumber
  5. });

  4. 根据i添加一个值

  1. dataset.push({
  2. key:i,
  3. value:newNumber
  4. });}

  5. 1/2 值函数

  1. var value=function(d){
  2. return d.value;
  3. };

  6. 2/2// 更新比例尺,免使纵坐标超出范围

yScale.domain([0,d3.max(dataset,value)]);//只要更新定义域就行了,映射到的值域不变
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>testD3-18-update.html</title>
  6. <script type="text/javascript" src="http://localhost:8080/spring/js/d3.v3.js"></script>
  7. </head>
  8. <body>
  9. <button>单击更新</button>
  10. <br>
  11. <p id="remove">单击删除</p>
  12. <p id="add">单击添加</p>
  13. <br>
  14. <script type="text/javascript">
  15. //键值对数据集
  16. var dataset = [
  17. {key:0,value:5},
  18. {key:1,value:10},
  19. {key:2,value:13},
  20. {key:3,value:19},
  21. {key:4,value:21},
  22. {key:5,value:25},
  23. {key:6,value:22},
  24. {key:7,value:18},
  25. {key:8,value:15},
  26. {key:9,value:13},
  27. {key:10,value:11},
  28. {key:11,value:12},
  29. {key:12,value:15},
  30. {key:13,value:20},
  31. {key:14,value:18},
  32. {key:15,value:17},
  33. {key:16,value:16},
  34. {key:17,value:18},
  35. {key:18,value:23},
  36. {key:19,value:25}];
  37. //设置SVG的高宽
  38. var w=600;
  39. var h=250;
  40. var barPadding = 1;
  41. //定义序数比例尺
  42. var xScale=d3.scale.ordinal()//序数比例尺
  43. .domain(d3.range(dataset.length))
  44. .rangeRoundBands([0,w],0.05);
  45. // 更新数据引用,包含下面所有关于要使用到d.value的地方
  46. var yScale=d3.scale.linear()//y仍然是线性比例尺
  47. .domain([0,d3.max(dataset,function(d){
  48. return d.value;
  49. })])
  50. .range([0,h]);
  51. // 定义键函数(简洁),以备数据绑定到元素的时候使用
  52. //把所有.data(dataset)改成.data(dataset,key)
  53. var key=function(d){
  54. return d.key;
  55. };
  56. //(6)1/2 值函数
  57. var value=function(d){
  58. return d.value;
  59. };
  60. //Create SVG element
  61. var svg = d3.select("body")//选中DOM中的目标元素
  62. .append("svg")//为目标元素附加上一个svg子元素
  63. .attr("width", w)//设置这个svg的宽
  64. .attr("height", h);//设置这个svg的高
  65. //为SVG添加条形
  66. svg.selectAll("rect")//选中空元素,表示即将创建这样的元素
  67. .data(dataset,key)//对此后的方法都执行dataset.length遍
  68. .enter()//数据元素值比前面选中的DOM元素多就创建一个新的DOM元素
  69. .append("rect")//取得enter的占位元素,并把rect追加到对应的DOM中
  70. .attr("x", function(d, i) {//设置横坐标,从0开始每次右移元素宽那么长(w / dataset.length)
  71. //return i * (w / dataset.length);
  72. return xScale(i);//这里使用序数比例尺,自己去找刚才划分好的档位
  73. })
  74. .attr("y", function(d) {//设置纵坐标,纵坐标正方向是从上往下的,所以条有多长就要设置起点是相对于h再向上移动条长
  75. return h - yScale(d.value);
  76. })
  77. //.attr("width", w / dataset.length - barPadding)//设置元素宽,留出间隙宽barPadding。
  78. .attr("width", xScale.rangeBand())//这里xScale比例尺已经设置间距了所以直接用
  79. .attr("height", function(d) {
  80. return yScale(d.value);
  81. })
  82. .attr("fill", function(d) {//设置RGB颜色与数值的关系
  83. return "rgb(0, 0, " + (d.value * 10) + ")";
  84. });
  85. //为条加上数值
  86. svg.selectAll("text")
  87. .data(dataset,key)
  88. .enter()
  89. .append("text")
  90. .text(function(d) {
  91. return d.value;
  92. })
  93. .attr("text-anchor", "middle")
  94. .attr("x", function(d, i) {
  95. return xScale(i)+xScale.rangeBand()/2;
  96. })
  97. .attr("y", function(d) {
  98. return h - yScale(d.value) + 14;
  99. })
  100. .attr("font-family", "sans-serif")
  101. .attr("font-size",function(d) {
  102. return xScale.rangeBand()/2;
  103. })
  104. .attr("fill", "white");
  105. //删除一条、添加一条
  106. d3.select("p")
  107. .on("click",function(){
  108. //(1)根据ID确定点击的是哪个标签
  109. var paragraphID=d3.select(this).attr("id") ;
  110. console.log(paragraphID);
  111. //(2)添加删除组合起来
  112. if(paragraphID=="add"){
  113. //数据集最后添加数值
  114. var maxValue=75;
  115. var newNumber =Math.floor(Math.random()*maxValue);//0-24的整数
  116. //(3)根据最后一个key添加一个值
  117. var lastKeyValue=dataset[dataset.length-1].key;
  118. dataset.push({
  119. key:lastKeyValue+1,
  120. value:newNumber
  121. });
  122. //更新X轴比例尺
  123. xScale.domain(d3.range(dataset.length));
  124. //选择所有条
  125. var bars=svg.selectAll("rect")
  126. .data(dataset,key); //绑定数据到元素集,返回更新的元素集
  127. var texts=svg.selectAll("text")
  128. .data(dataset,key);
  129. //添加条形元素到最右边
  130. bars.enter()
  131. .append("rect")
  132. .attr("x",w);//在SVG最右边,不可见
  133. //
  134. texts.enter()
  135. .append("text");
  136. //更新新矩形到可见范围内
  137. //并在这个时候根据数据集为每个条设置对应的属性
  138. bars.transition()
  139. .duration(500)
  140. .attr("x", function(d, i) {
  141. return xScale(i) ;
  142. })//每个X对应到它相应的档位上
  143. .attr("y", function(d) {
  144. return h - yScale(d.value) ;
  145. })
  146. .attr("width", xScale.rangeBand())//这里xScale比例尺已经设置间距了所以直接用
  147. .attr("height", function(d) {
  148. return yScale(d.value);
  149. })
  150. .attr("fill", function(d) {//设置RGB颜色与数值的关系
  151. return "rgb(0, 0, " + (d.value * 10) + ")";
  152. });
  153. //
  154. texts.transition()
  155. .duration(500)
  156. .text(function(d) {
  157. return d.value;
  158. })
  159. .attr("text-anchor", "middle")
  160. .attr("x", function(d, i) {
  161. return xScale(i)+xScale.rangeBand()/2;
  162. })
  163. .attr("y", function(d) {
  164. return h - yScale(d.value) + 14;
  165. })
  166. .attr("font-family", "sans-serif")
  167. .attr("font-size", "12px")
  168. .attr("fill", "red");
  169. }else if(paragraphID=="remove"){
  170. //(4)删除的操作
  171. //选择所有条
  172. dataset.shift();
  173. //更新X轴比例尺
  174. xScale.domain(d3.range(dataset.length));
  175. var bars=svg.selectAll("rect")
  176. .data(dataset,key);
  177. //从左侧退出
  178. bars.exit()
  179. .transition()
  180. .duration(500)
  181. .attr("x", -xScale.rangeBand())//w-xScale.rangeBand()间隙宽其实其他负数也行
  182. .remove();
  183. }
  184. });
  185. // 更新条形数长短的代码,需要一个button标签配合
  186. //特别注意:这里选中的元素必须在d3选择器之前,或许要先加载完了元素才能被选中
  187. d3.select("button")
  188. .on("click",function(){
  189. // 新数据集,随机数组
  190. var numValues=dataset.length;
  191. dataset=[];
  192. var maxValue=75;
  193. var newNumber;
  194. for(var i=0;i<numValues;i++){
  195. newNumber=Math.floor(Math.random()*maxValue);//0-24的整数
  196. //(5)根据i添加一个值
  197. dataset.push({
  198. key:i,
  199. value:newNumber
  200. });
  201. }
  202. //(6)1/2
  203. // 更新比例尺,免使纵坐标超出范围
  204. yScale.domain([0,d3.max(dataset,value)]);//只要更新定义域就行了,映射到的值域不变
  205. //更新所有的矩形
  206. svg.selectAll("rect")
  207. .data(dataset,key)
  208. .transition()// 加上过渡动画
  209. .delay(function(d,i){
  210. return i/dataset.length*1000;
  211. })//指定过度什么时间开始,可以用函数控制每一条的动画时间,这样就可得到钢琴版的效果
  212. .duration(2000)// 加上动画的持续时间,以毫秒计算
  213. .ease("linear")// 缓动函数:有circle(加速)elastic(伸缩),linear(匀速),bounce(弹跳)
  214. .attr("y",function(d){
  215. return h-yScale(d.value);
  216. })
  217. .attr("height",function(d){
  218. return yScale(d.value);
  219. });
  220. // 更新条上的数值
  221. svg.selectAll("text")
  222. .data(dataset,key)
  223. .text(function(d) {
  224. return d.value;
  225. })
  226. .attr("text-anchor", "middle")
  227. .attr("x", function(d, i) {
  228. return xScale(i)+xScale.rangeBand()/2;
  229. })
  230. .attr("y", function(d) {
  231. return h - yScale(d.value) + 14;
  232. })
  233. .attr("font-family", "sans-serif")
  234. .attr("font-size", "12px")
  235. .attr("fill", "red");
  236. });
  237. </script>
  238. </body>
  239. </html>

上一篇:【D3.js数据可视化系列教程】--(十五)SVG基本图形绘制


下一篇:d3.js dagre-d3.js使用中的坑