当前位置: 代码迷 >> JavaScript >> 【D3.V3.js数据可视化系列课程】(二十二)-交互图标之提示条
  详细解决方案

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

热度:330   发布时间:2013-11-03 15:39:14.0
【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"
 })

 

3 div

<!-- (1)创建div提示层 -->


 <div id="tooltip" class="hildden">
  <p><strong>提示:</strong></p>
  <p><span id="value">100</span>%</p>
 </div>

/*(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;
 }
  

//(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);
 })
 //移除提示条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 element
var 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>

  相关解决方案