【D3.V3.js数据可视化系列教程】(二十二)--交互图标之提示条
三种方案:
1 默认//(1)1/2追加默认格式的提示
.append("title")
//(1)2/2追加提示文字
.text(function(d){
return "This Value Is "+d.value;
});
2 svg
.on("mouseover",function(d){
//(1)取得提示显示的位置
var xPosition=parseFloat(d3.select(this).attr("x"))+xScale.rangeBand()/2;
var yPosition=parseFloat(d3.select(this).attr("y"))+24;
//(2)创建提示条SVG
svg.append("text")
.attr("id","tooltip")//设置id便于移除提示
.attr("x",xPosition)
.attr("y",yPosition)
.attr("text-anchor","middle")
.attr("font-family","sans-setif")
.attr("font-size","11px")
.attr("font-weight","bold")
.attr("fill","white")
.text(d.value);
})
//(3)移除提示条SVG
.on("mouseout",function(){
d3.select("#tooltip").remove();//ID 选择的语法:"#tooltip"
})
<div id="tooltip" class="hildden">
<p><strong>提示:</strong></p>
<p><span id="value">100</span>%</p>
</div>
#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;
}
.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);
})
//移除提示条SVG
.on("mouseout",function(){
//(4)添加隐藏类
d3.select("#tooltip").classed("hidden",true);//ID 选择的语法:"#tooltip"
})
;
但是最后没有出现预想的效果,不知道为什么
<!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 :red;}/* 过渡效果*/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">单击删除</p><p id="add">单击添加</p><!-- (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);});};//Create SVG elementvar 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);})//移除提示条 .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.select("p").on("click",function(){//根据ID确定点击的是哪个标签var paragraphID=d3.select(this).attr("id") ; console.log(paragraphID);//添加删除组合起来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().duration(500).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 if(paragraphID=="remove"){//删除的操作//选择所有条dataset.shift();//更新X轴比例尺xScale.domain(d3.range(dataset.length));var bars=svg.selectAll("rect").data(dataset,key); //从左侧退出bars.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>