【D3.js数据可视化系列教程】(十六)--更新、过度和动画

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/zhang__tianxu/article/details/14044261


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值