创建条形时就加上事件,实现鼠标滑过是出现水润丝滑的过度效果。
//(1)鼠标悬停时变为橘黄色
.on("mouseover",function(){d3.select(this)
.attr("fill","orange");
})
//(2)鼠标离开时恢复,利用之前学习的动画慢慢过渡
.on("mouseout",function(d){d3.select(this)
.transition()
.duration(250)
.attr("fill","rgb(0,0,"+(d.value*10)+")");
})
<!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> </head> <body> <button>单击更新</button> <br> <p id="remove">单击删除</p> <p id="add">单击添加</p> <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; }; //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) + ")"; }) //(1)鼠标悬停时变为橘黄色 .on("mouseover",function(){ d3.select(this) .attr("fill","orange"); }) //(2)鼠标离开时恢复,利用之前学习的动画慢慢过渡 .on("mouseout",function(d){ d3.select(this) .transition() .duration(250) .attr("fill","rgb(0,0,"+(d.value*10)+")"); }) ; //为条加上数值 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>