Vue整合d3.v5.js制作--折线图(line)先上效果图(x轴固定为时间轴):
图中出现的悬浮框是⿏标悬停效果
1、环境说明:
vue版本:"vue": "^2.5.2"
d3版本:"d3": "^5.9.1"
2、Line.vue源码
1 <template>
2 <div class="d3line" :id="id">
3 </div>
4 </template>
5
6 <script>
7 import * as d3 from 'd3'
8 export default {
9 name: 'd3line',
10 props: {
11id: String,
12 width: Number,
13 height: Number,
14 dataset: Array
15 },
16 mounted() {
17 this.init();
18 },
19 methods: {
20 init() {
21 d3.select("#svg" + this.id).remove();
22 let width = this.width ? this.width : 600;
23 let height = this.height ? this.height : 600;
24 let padding = {
25 left: 80,
26 right: 50,
27 top: 50,
28 bottom: 50
29 }
30 let colorZ = d3.scaleOrdinal(d3.schemeDark2)
31 let parseTime = d3.timeParse("%Y-%m-%d")
32 let xScale = d3.scaleTime().range([0, width - padding.left - padding.right])
33 let dates = this.dataset.flatMap((d) => d.value.map(v => parseTime(v.key)))
34 xScale.domain([d3.min(dates), d3.max(dates)])
35 let yScale = d3.scaleLinear().range([height - p - padding.bottom, 0])
36 yScale.domain([0, d3.max(this.dataset.flatMap((d) => d.value.map( v => v.value) )) + 2])
37 let xAxis = d3.axisBottom(xScale).tickFormat(d => d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate())
38 let yAxis = d3.axisLeft(yScale)
39 let svg = d3.select("#" + this.id).append("svg").attr("width", width).attr("height", height).attr("id", "svg" + this.id);
40 svg.append('g')
41 .attr('transform', 'translate(' + padding.left + ',' + (height - padding.bottom) + ')')
42 .call(xAxis)
43 .selectAll('text')
44 .attr('dx', -20)
45 .attr('dy', 10)
46 .attr('transform', 'rotate(-20)')
47 .style('font-weight', 'bold')
48 svg.append('g')
49 .attr('transform', 'translate(' + padding.left + ',' + p + ')')
50 .call(yAxis)
51 .selectAll('text')
52 .style('font-weight', 'bold')
53 let line = d3.line().x(d => xScale(parseTime(d.key))).y(d => yScale(d.value))
54 this.dataset.forEach((v, vi) => {
55 let tp_x = 0,
56 tp_y =0;
57 svg.append("path")
58 .attr('d' , line(v.value))
59 .attr('transform', 'translate(' + padding.left + ',' + p + ')')
60 .attr('fill', 'none')
61 .attr('stroke', (d, i) => colorZ(vi))
62 .attr("stroke-width", 2)
63 .style('stroke-dasharray', function(d, i) {
64 return d3.select(this).node().getTotalLength();
65 })
66 .style('stroke-dashoffset', function(d, i) {
67 return d3.select(this).node().getTotalLength();
68 })
69 .transition()
70 .duration(2000)
71 .ease(d3.easePolyOut)
72 .delay((d, i) => i * 200)
73 .style('stroke-dashoffset', 0)
74 svg.selectAll('circle1')
75 .data(v.value)
76 .enter()
77 .append('circle')
78 .attr('cx', (d, i) => {
79 let x = xScale(parseTime(d.key))
80if (i === v.value.length - 1) tp_x = x - 40
81 return x
82 })
83 .attr('cy', (d, i) => {
84 let y = yScale(d.value)
85if (i === v.value.length - 1) tp_y = y - 10
86 return y
87 })
88 .attr('r', 2)
89 .attr('transform', 'translate(' + padding.left + ',' + p + ')')
90 .style("fill", (d, i) => colorZ(vi))
91 .on("mouseover", (d, i) => {
92 let g = svg.append('g')
93 .attr('id', `hoverg${vi}${d.key}${d.value}`)
94 .attr("transform", "translate(" + (xScale(parseTime(d.key)) - 20) + "," + (yScale(d.value) + 30) + ")" )
95 g.append("rect")
96 .attr("x", function(d){ return BBox().x - 3;})
97 .attr("y", function(d, i){ return BBox().y - 20})
98 .attr("width", 110)
99 .attr("height", 25)
100 .style("fill", "#fffbf0")
101 g.append('text')
102 .text(`${d.key}:${d.value}`)
103 .style("fill", colorZ(vi))
104 })
105 .on("mouseout", (d) => d3.select(`#hoverg${vi}${d.key}${d.value}`).remove())
106 .transition()
107 .duration(1500)
108 .ease(d3.easePolyIn)
109 .delay((d, i) => i * 200)
110 .attr('r', 5)
111// svg.selectAll('text1')
112// .data([v.name])
113// .enter()
114// .append('text')制作svg图片
115// .attr('dx', (d, i) => tp_x)
116// .attr('dy', (d, i) => tp_y)
117// .attr('transform', 'translate(' + padding.left + ',' + p + ')')
118// .text((d) => d)
119// .style("fill", (d, i) => colorZ(vi))
120// .style('font-weight', 'bold')
121 svg.append('text')
122 .attr('dx', tp_x)
123 .attr('dy', tp_y)
124 .attr('transform', 'translate(' + padding.left + ',' + p + ')')
125 .text(v.name)
126 .style("fill", colorZ(vi))
127 .style('font-weight', 'bold')
128 })
129 }
130 },
131 watch: {
132 dataset() {
133 this.init();
134 }
135 }
136 }
137 </script>
138
139 <style>
140
141 </style>
3、使⽤⽰例
1 <template>
2 <div id="test">
3 <!-- ⼀定要传进去⼀个id,随便传⼀个 -->
4 <d3line id="line" :dataset="data1"></d3line>
5 </div>
6 </template>
7
8 <script>
9 import d3line from '@/components/d3/Line'
10 export default {
11 name: 'test',
12 data() {
13 return {
14 data1: [
15 {
16'name': '哈尔滨',
17'value': [{key: '2015-1-1', value: 10}, {key: '2015-1-2', value: 12}, {key: '2015-1-3', value: 13}, {key: '2015-1-17', value: 17}]
18 },
19 {
20'name': '海南',
21'value': [{key: '2015-1-1', value: 9}, {key: '2015-1-2', value: 48}, {key: '2015-1-3', value: 5}, {key: '2015-1-17', value: 49}]
22 },
23 {
24'name': '天津',
25'value': [{key: '2015-1-2', value: 30}, {key: '2015-1-3', value: 1}, {key: '2015-1-4', value: 32}, {key: '2015-1-5', value: 10}]
26 }
27 ]
28 }
29 },
30 components: {
31 d3line
32 },
33 methods: {
34
35 }
36 }
37 </script>
38
39 <style scoped>
40 </style>
4、参考资料
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论