版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
最后效果:单击任何一个条就能重新从左到右升序排序
1. 1/2条排序函数
-
var sortBars=
function(){
-
svg.selectAll(
"rect")
-
.sort(
function(a,b){
//对数据集升序排序
-
return d3.ascending(a.value,b.value);
//这个地方注意是键值对所以要加上值的引用b.value
-
})
-
.transition()
-
.duration(
1000)
-
.attr(
"x",
function(d,i){
//对排序之后的横坐标重排
-
return xScale(i);
-
});
-
};
2. 2/2点击排序
-
.on(
"click",
function(){
-
sortBars();
-
});
-
<!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;
-
};
-
//(1)1/2条排序函数
-
var
sortBars=
function()
{
-
svg.selectAll(
"rect"
)
-
.sort(
function(a,b)
{
//对数据集升序排序
-
return
d3.ascending(a.value,b.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(
"mouseover"
,
function()
{
-
d3.select(
this
)
-
.attr(
"fill"
,
"orange"
);
-
})
-
//鼠标离开时恢复,利用之前学习的动画慢慢过渡
-
.on(
"mouseout"
,
function(d)
{
-
d3.select(
this
)
-
.transition()
-
.duration(
250
)
-
.attr(
"fill"
,
"rgb(0,0,"
+(d.value*
10
)+
")"
);
-
})
-
//(1)2/2点击排序
-
.on(
"click"
,
function()
{
-
sortBars();
-
});
-
-
//为条加上数值
-
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>