【D3.js数据可视化系列教程】(二十)--交互图表之条形图排序

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

最后效果:单击任何一个条就能重新从左到右升序排序

  1. 1/2条排序函数


    
    
  1. var sortBars= function(){
  2. svg.selectAll( "rect")
  3. .sort( function(a,b){ //对数据集升序排序
  4. return d3.ascending(a.value,b.value); //这个地方注意是键值对所以要加上值的引用b.value
  5. })
  6. .transition()
  7. .duration( 1000)
  8. .attr( "x", function(d,i){ //对排序之后的横坐标重排
  9. return xScale(i);
  10. });
  11. };

  2. 2/2点击排序


    
    
  1. .on( "click", function(){
  2. sortBars();
  3. });

    
    
  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. //值函数
  57. var value= function(d) {
  58. return d.value;
  59. };
  60. //(1)1/2条排序函数
  61. var sortBars= function() {
  62. svg.selectAll( "rect" )
  63. .sort( function(a,b) { //对数据集升序排序
  64. return d3.ascending(a.value,b.value); //这个地方注意是键值对所以要加上值的引用b.value
  65. })
  66. .transition()
  67. .duration( 1000 )
  68. .attr( "x" , function(d,i) { //对排序之后的横坐标重排
  69. return xScale(i);
  70. });
  71. };
  72. //Create SVG element
  73. var svg = d3.select( "body" ) //选中DOM中的目标元素
  74. .append( "svg" ) //为目标元素附加上一个svg子元素
  75. .attr( "width" , w) //设置这个svg的宽
  76. .attr( "height" , h); //设置这个svg的高
  77. //为SVG添加条形
  78. svg.selectAll( "rect" ) //选中空元素,表示即将创建这样的元素
  79. .data(dataset,key) //对此后的方法都执行dataset.length遍
  80. .enter() //数据元素值比前面选中的DOM元素多就创建一个新的DOM元素
  81. .append( "rect" ) //取得enter的占位元素,并把rect追加到对应的DOM中
  82. .attr( "x" , function(d, i) { //设置横坐标,从0开始每次右移元素宽那么长(w / dataset.length)
  83. //return i * (w / dataset.length);
  84. return xScale(i); //这里使用序数比例尺,自己去找刚才划分好的档位
  85. })
  86. .attr( "y" , function(d) { //设置纵坐标,纵坐标正方向是从上往下的,所以条有多长就要设置起点是相对于h再向上移动条长
  87. return h - yScale(d.value);
  88. })
  89. //.attr("width", w / dataset.length - barPadding)//设置元素宽,留出间隙宽barPadding。
  90. .attr( "width" , xScale.rangeBand()) //这里xScale比例尺已经设置间距了所以直接用
  91. .attr( "height" , function(d) {
  92. return yScale(d.value);
  93. })
  94. .attr( "fill" , function(d) { //设置RGB颜色与数值的关系
  95. return "rgb(0, 0, " + (d.value * 10 ) + ")" ;
  96. })
  97. //鼠标悬停时变为橘黄色
  98. .on( "mouseover" , function() {
  99. d3.select( this )
  100. .attr( "fill" , "orange" );
  101. })
  102. //鼠标离开时恢复,利用之前学习的动画慢慢过渡
  103. .on( "mouseout" , function(d) {
  104. d3.select( this )
  105. .transition()
  106. .duration( 250 )
  107. .attr( "fill" , "rgb(0,0," +(d.value* 10 )+ ")" );
  108. })
  109. //(1)2/2点击排序
  110. .on( "click" , function() {
  111. sortBars();
  112. });
  113. //为条加上数值
  114. svg.selectAll( "text" )
  115. .data(dataset,key)
  116. .enter()
  117. .append( "text" )
  118. .text( function(d) {
  119. return d.value;
  120. })
  121. .attr( "text-anchor" , "middle" )
  122. .attr( "x" , function(d, i) {
  123. return xScale(i)+xScale.rangeBand()/ 2 ;
  124. })
  125. .attr( "y" , function(d) {
  126. return h - yScale(d.value) + 14 ;
  127. })
  128. .attr( "font-family" , "sans-serif" )
  129. .attr( "font-size" , function(d) {
  130. return xScale.rangeBand()/ 2 ;
  131. })
  132. .attr( "fill" , "white" );
  133. //删除一条、添加一条
  134. d3.select( "p" )
  135. .on( "click" , function() {
  136. //根据ID确定点击的是哪个标签
  137. var paragraphID=d3.select( this ).attr( "id" ) ;
  138. console .log(paragraphID);
  139. //添加删除组合起来
  140. if (paragraphID== "add" ){
  141. //数据集最后添加数值
  142. var maxValue= 75 ;
  143. var newNumber = Math .floor( Math .random()*maxValue); //0-24的整数
  144. //根据最后一个key添加一个值
  145. var lastKeyValue=dataset[dataset.length- 1 ].key;
  146. dataset.push({
  147. key:lastKeyValue+ 1 ,
  148. value:newNumber
  149. });
  150. //更新X轴比例尺
  151. xScale.domain(d3.range(dataset.length));
  152. var bars=svg.selectAll( "rect" )
  153. .data(dataset,key); //绑定数据到元素集,返回更新的元素集
  154. var texts=svg.selectAll( "text" )
  155. .data(dataset,key);
  156. //添加条形元素到最右边
  157. bars.enter()
  158. .append( "rect" )
  159. .attr( "x" ,w); //在SVG最右边,不可见
  160. texts.enter()
  161. .append( "text" );
  162. //更新新矩形到可见范围内
  163. //并在这个时候根据数据集为每个条设置对应的属性
  164. bars.transition()
  165. .duration( 500 )
  166. .attr( "x" , function(d, i) {
  167. return xScale(i) ;
  168. }) //每个X对应到它相应的档位上
  169. .attr( "y" , function(d) {
  170. return h - yScale(d.value) ;
  171. })
  172. .attr( "width" , xScale.rangeBand()) //这里xScale比例尺已经设置间距了所以直接用
  173. .attr( "height" , function(d) {
  174. return yScale(d.value);
  175. })
  176. .attr( "fill" , function(d) { //设置RGB颜色与数值的关系
  177. return "rgb(0, 0, " + (d.value * 10 ) + ")" ;
  178. });
  179. //
  180. texts.transition()
  181. .duration( 500 )
  182. .text( function(d) {
  183. return d.value;
  184. })
  185. .attr( "text-anchor" , "middle" )
  186. .attr( "x" , function(d, i) {
  187. return xScale(i)+xScale.rangeBand()/ 2 ;
  188. })
  189. .attr( "y" , function(d) {
  190. return h - yScale(d.value) + 14 ;
  191. })
  192. .attr( "font-family" , "sans-serif" )
  193. .attr( "font-size" , "12px" )
  194. .attr( "fill" , "red" );
  195. } else if (paragraphID== "remove" ){
  196. //删除的操作
  197. //选择所有条
  198. dataset.shift();
  199. //更新X轴比例尺
  200. xScale.domain(d3.range(dataset.length));
  201. var bars=svg.selectAll( "rect" ).data(dataset,key);
  202. //从左侧退出
  203. bars.exit()
  204. .transition()
  205. .duration( 500 )
  206. .attr( "x" , -xScale.rangeBand()) //w-xScale.rangeBand()间隙宽其实其他负数也行
  207. .remove();
  208. }
  209. });
  210. // 更新条形数长短的代码,需要一个button标签配合
  211. //特别注意:这里选中的元素必须在d3选择器之前,或许要先加载完了元素才能被选中
  212. d3.select( "button" )
  213. .on( "click" , function() {
  214. // 新数据集,随机数组
  215. var numValues=dataset.length;
  216. dataset=[];
  217. var maxValue= 75 ;
  218. var newNumber;
  219. for ( var i= 0 ;i<numValues;i++){
  220. newNumber= Math .floor( Math .random()*maxValue); //0-24的整数
  221. //根据i添加一个值
  222. dataset.push({
  223. key:i,
  224. value:newNumber
  225. });
  226. }
  227. // 更新比例尺,免使纵坐标超出范围
  228. yScale.domain([ 0 ,d3.max(dataset,value)]); //只要更新定义域就行了,映射到的值域不变
  229. //更新所有的矩形
  230. svg.selectAll( "rect" )
  231. .data(dataset,key)
  232. .transition() // 加上过渡动画
  233. .delay( function(d,i) {
  234. return i/dataset.length* 1000 ;
  235. }) //指定过度什么时间开始,可以用函数控制每一条的动画时间,这样就可得到钢琴版的效果
  236. .duration( 2000 ) // 加上动画的持续时间,以毫秒计算
  237. .ease( "linear" ) // 缓动函数:有circle(加速)elastic(伸缩),linear(匀速),bounce(弹跳)
  238. .attr( "y" , function(d) {
  239. return h-yScale(d.value);
  240. })
  241. .attr( "height" , function(d) {
  242. return yScale(d.value);
  243. });
  244. // 更新条上的数值
  245. svg.selectAll( "text" )
  246. .data(dataset,key)
  247. .text( function(d) {
  248. return d.value;
  249. })
  250. .attr( "text-anchor" , "middle" )
  251. .attr( "x" , function(d, i) {
  252. return xScale(i)+xScale.rangeBand()/ 2 ;
  253. })
  254. .attr( "y" , function(d) {
  255. return h - yScale(d.value) + 14 ;
  256. })
  257. .attr( "font-family" , "sans-serif" )
  258. .attr( "font-size" , "12px" )
  259. .attr( "fill" , "red" );
  260. });
  261. </script>
  262. </body>
  263. </html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值