一. api讲解
* .attr(xxx) .transition() .attr(xxx),transition()表示添加过渡,也就是从前一个属性过渡到后一个属性
* .duration(2000),表示过渡时间持续2秒
* .delay(500),表示延迟0.4秒后再进行过渡
* .ease(d3.easeElasticInOut)表示过渡方式,注意这里和v3版本的区别
二. vue使用
<
template
lang=
'pug'
>
div
.histogram-pane(
:id=
"id")
svg
</
template
>
<
script
>
/**
* 含有动画的图表
*/
import
*
as
d3
from
'd3'
export
default {
name:
'',
data () {
return {
id:
''
}
},
methods: {
uuid () {
function
s4 () {
return
Math.
floor((
1 +
Math.
random()) *
0x10000)
.
toString(
16)
.
substring(
1)
}
return (
s4() +
s4() +
'-' +
s4() +
'-' +
s4() +
'-' +
s4() +
'-' +
s4() +
s4() +
s4()
)
},
},
created () {
this.
id =
this.
uuid()
},
mounted () {
//1.创建svg画布
let
marge = {
top:
60,
bottom:
60,
left:
60,
right:
60 }
// let width = document.getElementById(this.id).clientWidth
// let height = document.getElementById(this.id).clientHeight
let
width =
600
let
height =
400
const
svg =
d3.
select(
this.
$el).
select(
'svg').
attr(
'width',
width).
attr(
'height',
height)
let
g =
svg.
append(
'g').
attr(
'transform',
'translate(' +
marge.
top +
',' +
marge.
left +
')')
//2.数据集
let
dataset = [
10,
20,
30,
23,
13,
40,
27,
35,
20,
33];
//3.坐标轴
//x轴序数比例尺(d3.scaleBand()并不是一个连续性的比例尺,domain()中使用一个数组,不过range()需要是一个连续域)
let
ranges =
d3.
range(
dataset.
length)
let
xcale =
d3.
scaleBand().
domain(
ranges).
range([
0,
width -
marge.
left -
marge.
right])
let
xAxis =
d3.
axisBottom(
xcale)
g.
append(
'g')
.
attr(
'transform',
'translate(' +
0 +
',' + (
height -
marge.
top -
marge.
bottom) +
')')
.
call(
xAxis)
//y轴线性比例尺
let
yscale =
d3.
scaleLinear().
domain([
0,
d3.
max(
dataset)]).
range([
height -
marge.
top -
marge.
bottom,
0])
let
yAxis =
d3.
axisLeft(
yscale)
g.
append(
'g')
.
attr(
'transform',
'translate(0, 0)')
.
call(
yAxis)
//4.为每个矩形和对应的文字创建一个分组<g>
let
gs =
g.
selectAll(
'rect')
.
data(
dataset)
.
enter()
.
append(
'g')
//5.绘制矩形
//设置矩形之间的间隙
let
rectPadding =
20
gs.
append(
'rect')
.
attr(
'x',
function(
d,
i) {
//xcale(i): 画布真实宽度(48)横坐标且从0开始, 0, 48, 96 ... 432
return
xcale(
i) +
rectPadding/
2
})
.
attr(
'width',
function() {
//xcale.step() 画布真实宽度(48):width-marge.left-marge.right/dataset.lenght
return
xcale.
step() -
rectPadding
})
.
attr(
'y',
function(
d){
let
min =
yscale.
domain()[
0]
//0 ; yscale(0) --- 280
return
yscale(
min)
//返回的是最大值
})
.
attr(
'height',
function(
d){
//默认开始高度为0
return
0
})
.
attr(
'fill',
'blue')
.
transition()
.
duration(
1000)
.
delay(
function(
d,
i){
return
i *
200
})
// .ease(d3.easeElasticInOut)
.
attr(
'y',
function(
d){
return
yscale(
d)
})
.
attr(
'height',
function(
d){
return
height -
marge.
top -
marge.
bottom -
yscale(
d)
})
//6.绘制文字
gs.
append(
'text')
.
attr(
'x',
function(
d,
i) {
return
xcale(
i) +
rectPadding/
2
})
.
attr(
'width',
function() {
return
xcale.
step() -
rectPadding
})
.
attr(
'y',
function(
d) {
// return yscale(d)
let
min =
yscale.
domain()[
0]
//0 ; yscale(0) --- 280
return
yscale(
min)
//返回的是最大值, 即在最底部
})
.
attr(
'dy',
rectPadding)
.
text(
function(
d) {
return
d
})
.
transition()
.
duration(
1000)
.
delay(
function(
d,
i){
return
i *
200;
})
//.ease(d3.easeElasticInOut)
.
attr(
"y",
function(
d){
return
yscale(
d);
});
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.histogram-pane {
width:
100%;
height:
1000px;
}
</
style
>