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

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

这里介绍三种典型的提示条方案:

  1. 默认


    
    
  1. element.append( "title") // 追加默认格式的提示
  2. .text( function(d){ // 追加提示文字
  3. return "提示文字:"+d.value;
  4. });

  2. svg


    
    
  1. .on( "mouseover", function(d){
  2. //(1)取得提示显示的位置
  3. var xPosition= parseFloat(d3.select( this).attr( "x"))+xScale.rangeBand()/ 2;
  4. var yPosition= parseFloat(d3.select( this).attr( "y"))+ 24;
  5. //(2)创建提示条SVG
  6. svg.append( "text")
  7. .attr( "id", "tooltip") //设置id便于移除提示
  8. .attr( "x",xPosition)
  9. .attr( "y",yPosition)
  10. .attr( "text-anchor", "middle")
  11. .attr( "font-family", "sans-setif")
  12. .attr( "font-size", "11px")
  13. .attr( "font-weight", "bold")
  14. .attr( "fill", "white")
  15. .text(d.value);
  16. })
  17. //(3)移除提示条SVG
  18. .on( "mouseout", function(){
  19. d3.select( "#tooltip").remove();
  20. })

  3. div

  • (1) 创建div提示层

    
          
          
    1. <div id="tooltip" class="hildden">
    2. <p> <strong> 提示: </strong> </p>
    3. <p> <span id="value"> 100 </span>% </p>
    4. v>
  • (2)给提示条加上样式


    
    
  1. #tooltip {
  2. position:absolute;
  3. width:200px;
  4. height:auto;
  5. padding:10px;
  6. background-color:white;
  7. -webkit-border-radius:10px;
  8. -moz-border-radius:10px;
  9. border-radius:10px;
  10. -webkit-box-shadow:4px 4px 10px rgba(0,0,0,0.4);
  11. -moz-box-shadow:4px 4px 10px rgba(0,0,0,0.4);
  12. box-shadow:4px 4px 10px rgba(0,0,0,0.4);
  13. pointer-events:none;
  14. }
  15. #tooltip .hidden {
  16. display:none;
  17. }
  18. #tooltip p {
  19. margin:0;
  20. font-family:sans-serif;
  21. font-size:16px;
  22. line-height:20px;
  23. }
  • (3)更新提示条的值和位置

    
    
  1. .on( "mouseover", function(d){
  2. //取得提示显示的位置
  3. var xPosition= parseFloat(d3.select( this).attr( "x"))+xScale.rangeBand()/ 2;
  4. var yPosition= parseFloat(d3.select( this).attr( "y"))/ 2+h/ 2;
  5. d3.select( "#tooltip")
  6. .style( "left",xPosition+ "px")
  7. .style( "top",yPosition+ "px")
  8. .select( "#value")
  9. .text(d.value);
  10. })
  11. //移除提示条SVG
  12. .on( "mouseout", function(){
  13. //(4)添加隐藏类
  14. d3.select( "#tooltip").classed( "hidden", true); //ID 选择的语法:"#tooltip"
  15. }) ;

    
    
  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. <style type="text/css">
  8. /* 鼠标悬停时变色*/
  9. rect :hover {
  10. fill :red ;
  11. }
  12. /* 过渡效果*/
  13. rect {
  14. -moz-transiton:all 0.3s ;
  15. -o-transiton:all 0.3s ;
  16. -webkit-transition:all 0.3s ;
  17. transition:all 0.3s
  18. }
  19. /*(2)给提示条加上样式*/
  20. #tooltip {
  21. position:absolute ;
  22. width:200px ;
  23. height:auto ;
  24. padding:10px ;
  25. background-color:white ;
  26. -webkit-border-radius:10px ;
  27. -moz-border-radius:10px ;
  28. border-radius:10px ;
  29. -webkit-box-shadow:4px 4px 10px rgba(0,0,0,0.4) ;
  30. -moz-box-shadow:4px 4px 10px rgba(0,0,0,0.4) ;
  31. box-shadow:4px 4px 10px rgba(0,0,0,0.4) ;
  32. pointer-events:none ;
  33. }
  34. #tooltip .hidden {
  35. display:none ;
  36. }
  37. #tooltip p {
  38. margin:0 ;
  39. font-family:sans-serif ;
  40. font-size:16px ;
  41. line-height:20px ;
  42. }
  43. </style>
  44. </head>
  45. <body>
  46. <button>单击更新 </button>
  47. <br>
  48. <p id="remove">单击删除 </p>
  49. <p id="add">单击添加 </p>
  50. <!-- (1)创建div提示层 -->
  51. <div id="tooltip" class="hildden">
  52. <p> <strong>提示: </strong> </p>
  53. <p> <span id="value">100 </span>% </p>
  54. </div>
  55. <br>
  56. <script type="text/javascript">
  57. //键值对数据集
  58. var dataset = [
  59. { key: 0 ,value: 5 },
  60. { key: 1 ,value: 10 },
  61. { key: 2 ,value: 13 },
  62. { key: 3 ,value: 19 },
  63. { key: 4 ,value: 21 },
  64. { key: 5 ,value: 25 },
  65. { key: 6 ,value: 22 },
  66. { key: 7 ,value: 18 },
  67. { key: 8 ,value: 15 },
  68. { key: 9 ,value: 13 },
  69. { key: 10 ,value: 11 },
  70. { key: 11 ,value: 12 },
  71. { key: 12 ,value: 15 },
  72. { key: 13 ,value: 20 },
  73. { key: 14 ,value: 18 },
  74. { key: 15 ,value: 17 },
  75. { key: 16 ,value: 16 },
  76. { key: 17 ,value: 18 },
  77. { key: 18 ,value: 23 },
  78. { key: 19 ,value: 25 }];
  79. //设置SVG的高宽
  80. var w= 600 ;
  81. var h= 250 ;
  82. var barPadding = 1 ;
  83. //定义序数比例尺
  84. var xScale=d3.scale.ordinal() //序数比例尺
  85. .domain(d3.range(dataset.length))
  86. .rangeRoundBands([ 0 ,w], 0.05 );
  87. // 更新数据引用,包含下面所有关于要使用到d.value的地方
  88. var yScale=d3.scale.linear() //y仍然是线性比例尺
  89. .domain([ 0 ,d3.max(dataset, function(d) {
  90. return d.value;
  91. })])
  92. .range([ 0 ,h]);
  93. // 定义键函数(简洁),以备数据绑定到元素的时候使用
  94. //把所有.data(dataset)改成.data(dataset,key)
  95. var key= function(d) {
  96. return d.key;
  97. };
  98. //值函数
  99. var value= function(d) {
  100. return d.value;
  101. };
  102. //条排序函数
  103. var sortOrders= false ;
  104. var sortBars= function() {
  105. sortOrders=!sortOrders; //(3)每点击一次排序方向改变
  106. svg.selectAll( "rect" )
  107. .sort( function(a,b) {
  108. if (sortOrders){
  109. //对数据集升序排序
  110. return d3.ascending(a.value,b.value); //这个地方注意是键值对所以要加上值的引用b.value
  111. } else {
  112. //对数据集降序排序
  113. return d3.descending(a.value,b.value);
  114. }
  115. })
  116. .transition()
  117. .duration( 1000 )
  118. .attr( "x" , function(d,i) { //对排序之后的横坐标重排
  119. return xScale(i);
  120. });
  121. };
  122. //创建SVG元素
  123. var svg = d3.select( "body" ) //选中DOM中的目标元素
  124. .append( "svg" ) //为目标元素附加上一个svg子元素
  125. .attr( "width" , w) //设置这个svg的宽
  126. .attr( "height" , h); //设置这个svg的高
  127. //为SVG添加条形
  128. svg.selectAll( "rect" ) //选中空元素,表示即将创建这样的元素
  129. .data(dataset,key) //对此后的方法都执行dataset.length遍
  130. .enter() //数据元素值比前面选中的DOM元素多就创建一个新的DOM元素
  131. .append( "rect" ) //取得enter的占位元素,并把rect追加到对应的DOM中
  132. .attr( "x" , function(d, i) { //设置横坐标,从0开始每次右移元素宽那么长(w / dataset.length)
  133. //return i * (w / dataset.length);
  134. return xScale(i); //这里使用序数比例尺,自己去找刚才划分好的档位
  135. })
  136. .attr( "y" , function(d) { //设置纵坐标,纵坐标正方向是从上往下的,所以条有多长就要设置起点是相对于h再向上移动条长
  137. return h - yScale(d.value);
  138. })
  139. //.attr("width", w / dataset.length - barPadding)//设置元素宽,留出间隙宽barPadding。
  140. .attr( "width" , xScale.rangeBand()) //这里xScale比例尺已经设置间距了所以直接用
  141. .attr( "height" , function(d) {
  142. return yScale(d.value);
  143. })
  144. .attr( "fill" , function(d) { //设置RGB颜色与数值的关系
  145. return "rgb(0, 0, " + (d.value * 10 ) + ")" ;
  146. })
  147. //点击排序
  148. .on( "click" , function() {
  149. sortBars();
  150. })
  151. //(3)更新提示条的值和位置
  152. .on( "mouseover" , function(d) {
  153. //取得提示显示的位置
  154. var xPosition= parseFloat (d3.select( this ).attr( "x" ))+xScale.rangeBand()/ 2 ;
  155. var yPosition= parseFloat (d3.select( this ).attr( "y" ))/ 2 +h/ 2 ;
  156. d3.select( "#tooltip" )
  157. .style( "left" ,xPosition+ "px" )
  158. .style( "top" ,yPosition+ "px" )
  159. .select( "#value" )
  160. .text(d.value);
  161. })
  162. //移除提示条
  163. .on( "mouseout" , function() {
  164. //(4)添加隐藏类
  165. d3.select( "#tooltip" ).classed( "hidden" , true ); //ID 选择的语法:"#tooltip"
  166. })
  167. ;
  168. //为条加上数值
  169. svg.selectAll( "text" )
  170. .data(dataset,key)
  171. .enter()
  172. .append( "text" )
  173. .text( function(d) {
  174. return d.value;
  175. })
  176. .attr( "text-anchor" , "middle" )
  177. .attr( "x" , function(d, i) {
  178. return xScale(i)+xScale.rangeBand()/ 2 ;
  179. })
  180. .attr( "y" , function(d) {
  181. return h - yScale(d.value) + 14 ;
  182. })
  183. .attr( "font-family" , "sans-serif" )
  184. .attr( "font-size" , function(d) {
  185. return xScale.rangeBand()/ 2 ;
  186. })
  187. .attr( "fill" , "white" );
  188. //删除一条、添加一条
  189. d3.select( "p" )
  190. .on( "click" , function() {
  191. //根据ID确定点击的是哪个标签
  192. var paragraphID=d3.select( this ).attr( "id" ) ;
  193. console .log(paragraphID);
  194. //添加删除组合起来
  195. if (paragraphID== "add" ){
  196. //数据集最后添加数值
  197. var maxValue= 75 ;
  198. var newNumber = Math .floor( Math .random()*maxValue); //0-24的整数
  199. //根据最后一个key添加一个值
  200. var lastKeyValue=dataset[dataset.length- 1 ].key;
  201. dataset.push({
  202. key:lastKeyValue+ 1 ,
  203. value:newNumber
  204. });
  205. //更新X轴比例尺
  206. xScale.domain(d3.range(dataset.length));
  207. //选择所有条
  208. var bars=svg.selectAll( "rect" )
  209. .data(dataset,key); //绑定数据到元素集,返回更新的元素集
  210. var texts=svg.selectAll( "text" )
  211. .data(dataset,key);
  212. //添加条形元素到最右边
  213. bars.enter()
  214. .append( "rect" )
  215. .attr( "x" ,w); //在SVG最右边,不可见
  216. //
  217. texts.enter()
  218. .append( "text" );
  219. //更新新矩形到可见范围内
  220. //并在这个时候根据数据集为每个条设置对应的属性
  221. bars.transition()
  222. .duration( 500 )
  223. .attr( "x" , function(d, i) {
  224. return xScale(i) ;
  225. }) //每个X对应到它相应的档位上
  226. .attr( "y" , function(d) {
  227. return h - yScale(d.value) ;
  228. })
  229. .attr( "width" , xScale.rangeBand()) //这里xScale比例尺已经设置间距了所以直接用
  230. .attr( "height" , function(d) {
  231. return yScale(d.value);
  232. })
  233. .attr( "fill" , function(d) { //设置RGB颜色与数值的关系
  234. return "rgb(0, 0, " + (d.value * 10 ) + ")" ;
  235. });
  236. //
  237. texts.transition()
  238. .duration( 500 )
  239. .text( function(d) {
  240. return d.value;
  241. })
  242. .attr( "text-anchor" , "middle" )
  243. .attr( "x" , function(d, i) {
  244. return xScale(i)+xScale.rangeBand()/ 2 ;
  245. })
  246. .attr( "y" , function(d) {
  247. return h - yScale(d.value) + 14 ;
  248. })
  249. .attr( "font-family" , "sans-serif" )
  250. .attr( "font-size" , "12px" )
  251. .attr( "fill" , "red" );
  252. } else if (paragraphID== "remove" ){
  253. //删除的操作
  254. //选择所有条
  255. dataset.shift();
  256. //更新X轴比例尺
  257. xScale.domain(d3.range(dataset.length));
  258. var bars=svg.selectAll( "rect" )
  259. .data(dataset,key);
  260. //从左侧退出
  261. bars.exit()
  262. .transition()
  263. .duration( 500 )
  264. .attr( "x" , -xScale.rangeBand()) //w-xScale.rangeBand()间隙宽其实其他负数也行
  265. .remove();
  266. }
  267. });
  268. // 更新条形数长短的代码,需要一个button标签配合
  269. //特别注意:这里选中的元素必须在d3选择器之前,或许要先加载完了元素才能被选中
  270. d3.select( "button" )
  271. .on( "click" , function() {
  272. // 新数据集,随机数组
  273. var numValues=dataset.length;
  274. dataset=[];
  275. var maxValue= 75 ;
  276. var newNumber;
  277. for ( var i= 0 ;i<numValues;i++){
  278. newNumber= Math .floor( Math .random()*maxValue); //0-24的整数
  279. //根据i添加一个值
  280. dataset.push({
  281. key:i,
  282. value:newNumber
  283. });
  284. }
  285. // 更新比例尺,免使纵坐标超出范围
  286. yScale.domain([ 0 ,d3.max(dataset,value)]); //只要更新定义域就行了,映射到的值域不变
  287. //更新所有的矩形
  288. svg.selectAll( "rect" )
  289. .data(dataset,key)
  290. .transition() // 加上过渡动画
  291. .delay( function(d,i) {
  292. return i/dataset.length* 1000 ;
  293. }) //指定过度什么时间开始,可以用函数控制每一条的动画时间,这样就可得到钢琴版的效果
  294. .duration( 2000 ) // 加上动画的持续时间,以毫秒计算
  295. .ease( "linear" ) // 缓动函数:有circle(加速)elastic(伸缩),linear(匀速),bounce(弹跳)
  296. .attr( "y" , function(d) {
  297. return h-yScale(d.value);
  298. })
  299. .attr( "height" , function(d) {
  300. return yScale(d.value);
  301. });
  302. // 更新条上的数值
  303. svg.selectAll( "text" )
  304. .data(dataset,key)
  305. .text( function(d) {
  306. return d.value;
  307. })
  308. .attr( "text-anchor" , "middle" )
  309. .attr( "x" , function(d, i) {
  310. return xScale(i)+xScale.rangeBand()/ 2 ;
  311. })
  312. .attr( "y" , function(d) {
  313. return h - yScale(d.value) + 14 ;
  314. })
  315. .attr( "font-family" , "sans-serif" )
  316. .attr( "font-size" , "12px" )
  317. .attr( "fill" , "red" );
  318. });
  319. </script>
  320. </body>
  321. </html>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值