最后效果:
单击更新能实现像之前那样的更新了。
但是,单击添加和删除时,只能捕获第一个p标签,不能捕获第二个。
1. 根据ID确定点击的是哪个标签
var paragraphID=d3.select(this).attr("id") ;
2. 添加删除组合起来
if(paragraphID=="add"){
3. 根据最后一个key添加一个值
- var lastKeyValue=dataset[dataset.length-1].key;
- dataset.push({
- key:lastKeyValue+1,
- value:newNumber
- });
4. 根据i添加一个值
- dataset.push({
- key:i,
- value:newNumber
- });}
5. 1/2 值函数
- var value=function(d){
- return d.value;
- };
6. 2/2// 更新比例尺,免使纵坐标超出范围
yScale.domain([0,d3.max(dataset,value)]);//只要更新定义域就行了,映射到的值域不变
- <!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;
- };
- //(6)1/2 值函数
- 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) + ")";
- });
- //为条加上数值
- 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(){
- //(1)根据ID确定点击的是哪个标签
- var paragraphID=d3.select(this).attr("id") ;
- console.log(paragraphID);
- //(2)添加删除组合起来
- if(paragraphID=="add"){
- //数据集最后添加数值
- var maxValue=75;
- var newNumber =Math.floor(Math.random()*maxValue);//0-24的整数
- //(3)根据最后一个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"){
- //(4)删除的操作
- //选择所有条
- 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的整数
- //(5)根据i添加一个值
- dataset.push({
- key:i,
- value:newNumber
- });
- }
- //(6)1/2
- // 更新比例尺,免使纵坐标超出范围
- 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>