用 d3.js 做一个简单的柱状
公司需要做一个和设计稿相同的图表,但是现有的 echarts
等图标库没有类似的东西,所以自己做了一个。
由于上次用 oCanvas
做的有性能问题,这次用 d3.js(svg)又重做了一遍。上次的文章可以看自定义 oCanvas 图形 - 自制柱状图。
引用 d3.js 框架
html
<script src="https://cdn.bootcss.com/d3/4.12.2/d3.js"></script>
1
dom
html
<div id="svg"></div>
1
编写
里面除了用到 SVG 的一些知识外,还用了 d3 中插值和过渡动画。
js
const initChart = (el, width, height, value, frontColor) => {
// const width = 50;
// const height = 500;
// const value = 60;
const backgroundColor = "rgba(34,151,255,0.5)";
// const frontColor = 'rgb(34,151,255)';
const lineColor = "rgb(255,255,255,0.5)";
const lineWidth = 1;
const points = [
[width / 2, height],
[width, height - width / 2],
[width, 0],
[0, 0],
[0, height - width / 2],
];
const points2string = (points) => points.map((arr) => arr.join(",")).join(" ");
const svg = d3.select(el).append("svg").attr("width", width).attr("height", height);
const clipPath = svg.append("defs").append("clipPath").attr("id", "clipPath");
clipPath.append("polygon").attr("points", points2string(points));
const chart = svg.append("g").attr("clip-path", "url(#clipPath)");
const background = chart
.append("rect")
.attr("fill", backgroundColor)
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
const frontHeight = (value / 100) * height;
const front = chart
.append("rect")
.attr("fill", frontColor)
.attr("x", 0)
.attr("y", height - frontHeight)
.attr("width", width)
.attr("height", frontHeight);
const text = chart
.append("text")
.attr("text-anchor", "middle")
.attr("fill", "#fff")
.attr("x", width / 2)
.attr("dy", 5)
.attr("y", height - frontHeight)
.text(value + "%");
for (let i = 1; i <= 10; i++) {
const p = [
[0, (height / 10) * i],
[width, (height / 10) * i],
];
chart.append("polyline").attr("points", points2string(p)).attr("stroke", lineColor).attr("stroke-width", lineWidth);
}
front.setValue = (value) => {
const frontHeight = (value / 100) * height;
const oldValue = parseInt(text.text());
front
.transition()
.duration(1000)
.attr("y", height - frontHeight)
.attr("height", frontHeight);
text
.transition()
.duration(1000)
.attr("y", height - frontHeight)
.tween("y", () => {
const i = d3.interpolate(oldValue, value);
return (t) => text.text(i(t).toFixed(0) + "%");
});
};
return front;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
演示代码
js
const chart = initChart("#svg", 50, 500, 60, "rgb(34,151,255)");
setInterval(function () {
chart.setValue(Math.random() * 100);
}, 1000);
1
2
3
4
2
3
4