
+++ client/views/components/MultiLineChart.vue
... | ... | @@ -0,0 +1,199 @@ |
1 | +<template> | |
2 | + <div class="chart-container" ref="chartdiv"></div> | |
3 | +</template> | |
4 | + | |
5 | +<script> | |
6 | +import * as am5 from '@amcharts/amcharts5'; | |
7 | +import * as am5xy from '@amcharts/amcharts5/xy'; | |
8 | +import am5themes_Animated from '@amcharts/amcharts5/themes/Animated'; | |
9 | + | |
10 | +export default { | |
11 | + props: { | |
12 | + chartData: { | |
13 | + type: Array, | |
14 | + required: true, | |
15 | + }, | |
16 | + keyMapping: { | |
17 | + type: Object, | |
18 | + }, | |
19 | + xField: { | |
20 | + type: String, | |
21 | + default: null | |
22 | + // required: true, | |
23 | + }, | |
24 | + }, | |
25 | + data() { | |
26 | + return { | |
27 | + chart: null, | |
28 | + }; | |
29 | + }, | |
30 | + methods: { | |
31 | + createChart(data, keyMapping, xField) { | |
32 | + console.log(typeof(xField)); | |
33 | + | |
34 | + | |
35 | + let coulmns = Object.keys(data[0]); | |
36 | + for(let i = 0; i < coulmns.length ; i++){ | |
37 | + if(coulmns[i] == xField){ | |
38 | + coulmns.splice(i,1); | |
39 | + } | |
40 | + } | |
41 | + | |
42 | + | |
43 | + let chartWarp = this.$refs["chartdiv"]; // 차트 상위 div ref 매칭 | |
44 | + chartWarp.innerHTML = ""; // 차트 상위 div 내용 초기화 (기존 차트 삭제) | |
45 | + let div = document.createElement("div"); // 차트를 담을 빈 div 생성 (차트 하위 div) | |
46 | + div.style.width = "100%"; // 차트를 담을 div의 넓이 | |
47 | + div.style.height = "100%"; // 차트를 담을 div의 높이 | |
48 | + chartWarp.appendChild(div); // 차트 상위 div 안에 차트 하위 div를 추가 | |
49 | + let root = am5.Root.new(div); // 차트 하위 div에 차트(root) 담기 | |
50 | + this.charts = root; // 차트 정보 전역에 담기 | |
51 | + | |
52 | + root._logo.dispose(); | |
53 | + | |
54 | + // Set themes | |
55 | + // https://www.amcharts.com/docs/v5/concepts/themes/ | |
56 | + root.setThemes([ | |
57 | + am5themes_Animated.new(root) | |
58 | + ]); | |
59 | + | |
60 | + | |
61 | + // Create chart | |
62 | + // https://www.amcharts.com/docs/v5/charts/xy-chart/ | |
63 | + let chart = root.container.children.push(am5xy.XYChart.new(root, { | |
64 | + panX: true, | |
65 | + panY: true, | |
66 | + wheelX: "panX", | |
67 | + wheelY: "zoomX", | |
68 | + layout: root.verticalLayout, | |
69 | + pinchZoomX: true | |
70 | + })); | |
71 | + | |
72 | + | |
73 | + // Add cursor | |
74 | + // https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/ | |
75 | + var cursor = chart.set("cursor", am5xy.XYCursor.new(root, { | |
76 | + behavior: "none" | |
77 | + })); | |
78 | + cursor.lineY.set("visible", false); | |
79 | + | |
80 | + | |
81 | + let xRenderer = am5xy.AxisRendererX.new(root, { | |
82 | + minorGridEnabled: true | |
83 | + }); | |
84 | + | |
85 | + xRenderer.grid.template.set("location", 0.5); | |
86 | + xRenderer.labels.template.setAll({ | |
87 | + location: 0.5, | |
88 | + multiLocation: 0.5 | |
89 | + }); | |
90 | + | |
91 | + let xAxis = chart.xAxes.push( | |
92 | + am5xy.CategoryAxis.new(root, { | |
93 | + categoryField: xField, | |
94 | + renderer: xRenderer, | |
95 | + tooltip: am5.Tooltip.new(root, {}) | |
96 | + }) | |
97 | + ); | |
98 | + | |
99 | + xAxis.data.setAll(data); | |
100 | + | |
101 | + let yAxis = chart.yAxes.push( | |
102 | + am5xy.ValueAxis.new(root, { | |
103 | + maxPrecision: 0, | |
104 | + renderer: am5xy.AxisRendererY.new(root, { | |
105 | + // inversed: true | |
106 | + }) | |
107 | + }) | |
108 | + ); | |
109 | + | |
110 | + for(let s = 0 ; s < coulmns.length; s++){ | |
111 | + this.makeSeries(chart,xField, xAxis ,yAxis, root,data,coulmns[s],coulmns[s]); | |
112 | + } | |
113 | + | |
114 | + chart.set("scrollbarX", am5.Scrollbar.new(root, { | |
115 | + orientation: "horizontal", | |
116 | + marginBottom: 20 | |
117 | + })); | |
118 | + | |
119 | + let legend = chart.children.push( | |
120 | + am5.Legend.new(root, { | |
121 | + centerX: am5.p50, | |
122 | + x: am5.p50 | |
123 | + }) | |
124 | + ); | |
125 | + | |
126 | + | |
127 | + // Make series change state when legend item is hovered | |
128 | + legend.itemContainers.template.states.create("hover", {}); | |
129 | + | |
130 | + legend.itemContainers.template.events.on("pointerover", function (e) { | |
131 | + e.target.dataItem.dataContext.hover(); | |
132 | + }); | |
133 | + | |
134 | + legend.itemContainers.template.events.on("pointerout", function (e) { | |
135 | + e.target.dataItem.dataContext.unhover(); | |
136 | + }); | |
137 | + | |
138 | + legend.data.setAll(chart.series.values); | |
139 | + | |
140 | + // Make stuff animate on load | |
141 | + // https://www.amcharts.com/docs/v5/concepts/animations/ | |
142 | + chart.appear(1000, 100); | |
143 | + }, | |
144 | + | |
145 | + makeSeries : function(chart,xField, xAxis ,yAxis ,root ,data , name, fieldName) { | |
146 | + let series = chart.series.push(am5xy.LineSeries.new(root, { | |
147 | + name: name, | |
148 | + xAxis: xAxis, | |
149 | + yAxis: yAxis, | |
150 | + valueYField: fieldName, | |
151 | + categoryXField: xField, | |
152 | + tooltip: am5.Tooltip.new(root, { | |
153 | + pointerOrientation: "horizontal", | |
154 | + labelText: "[bold]{name}[/]\n{categoryX}: {valueY}" | |
155 | + }) | |
156 | + })); | |
157 | + | |
158 | + series.bullets.push(function () { | |
159 | + return am5.Bullet.new(root, { | |
160 | + sprite: am5.Circle.new(root, { | |
161 | + radius: 5, | |
162 | + fill: series.get("fill") | |
163 | + }) | |
164 | + }); | |
165 | + }); | |
166 | + | |
167 | + series.set("setStateOnChildren", true); | |
168 | + series.states.create("hover", {}); | |
169 | + | |
170 | + series.mainContainer.set("setStateOnChildren", true); | |
171 | + series.mainContainer.states.create("hover", {}); | |
172 | + | |
173 | + // series.strokes.template.states.create("hover", { | |
174 | + // strokeWidth: 4 | |
175 | + // }); | |
176 | + | |
177 | + series.data.setAll(data); | |
178 | + series.appear(1000); | |
179 | + } | |
180 | + }, | |
181 | + watch: { | |
182 | + 'chartData': function (newData) { | |
183 | + console.log('newData - ', newData) | |
184 | + this.createChart(newData,this.keyMapping,this.xField); | |
185 | + } | |
186 | + }, | |
187 | + mounted() { | |
188 | + // this.chart = this.createChart(this.data, this.xField, this.yField, this.colors, this.unit); | |
189 | + }, | |
190 | +}; | |
191 | +</script> | |
192 | + | |
193 | +<style scoped> | |
194 | +.chart-container { | |
195 | + width: 100%; | |
196 | + height: 400px; | |
197 | +} | |
198 | +</style> | |
199 | + (No newline at end of file) |
--- client/views/components/StackedColumnChart.vue
+++ client/views/components/StackedColumnChart.vue
... | ... | @@ -47,16 +47,12 @@ |
47 | 47 |
|
48 | 48 |
let coulmns = Object.keys(data[0]); |
49 | 49 |
|
50 |
- |
|
51 |
- |
|
52 | 50 |
for(let i = 0; i < coulmns.length ; i++){ |
53 | 51 |
if(coulmns[i] == xField){ |
54 | 52 |
coulmns.splice(i,1); |
55 | 53 |
} |
56 |
- |
|
57 | 54 |
} |
58 |
- console.log('data',data) |
|
59 |
- console.log('coulmns',coulmns) |
|
55 |
+ |
|
60 | 56 |
|
61 | 57 |
|
62 | 58 |
// Set themes |
--- client/views/pages/Main/Main.vue
+++ client/views/pages/Main/Main.vue
... | ... | @@ -21,7 +21,7 @@ |
21 | 21 |
<p>군집/월별 점검 횟수</p> |
22 | 22 |
</div> |
23 | 23 |
</div> |
24 |
- <!-- <VerticalBarChart :chartData="emptyTimeData" :xField="'time'" :yField="'mean'" :color="['#1c7ed6','#74c0fc','#1864ab']" /> --> |
|
24 |
+ <MultiLineChart :chartData="emptyClusterData1" :xField="'month'" /> |
|
25 | 25 |
</div> |
26 | 26 |
<div class="content-box"> |
27 | 27 |
<div class="chart-title"> |
... | ... | @@ -64,6 +64,8 @@ |
64 | 64 |
import LineChart from '../../components/LineChart.vue'; |
65 | 65 |
import DataChart1 from '../../components/DataChart1.vue'; |
66 | 66 |
import StackedColumnChart from '../../components/StackedColumnChart.vue'; |
67 |
+import MultiLineChart from '../../components/MultiLineChart.vue'; |
|
68 |
+ |
|
67 | 69 |
|
68 | 70 |
|
69 | 71 |
export default { |
... | ... | @@ -107,13 +109,28 @@ |
107 | 109 |
{ Cluster_Labels:2.0, mean:158.4532030077}, |
108 | 110 |
{ Cluster_Labels:3.0, mean:60.4299174302 }, |
109 | 111 |
], |
112 |
+ emptyClusterData1: [], |
|
113 |
+ clusterData1 :[ |
|
114 |
+ { "month": 1, "0.0": 158, "1.0": 217, "2.0": 36, "3.0": 336}, |
|
115 |
+ { "month": 2, "0.0": 149, "1.0": 211, "2.0": 32, "3.0": 357 }, |
|
116 |
+ { "month": 3, "0.0": 229, "1.0": 239, "2.0": 41, "3.0": 373 }, |
|
117 |
+ { "month": 4, "0.0": 194, "1.0": 238, "2.0": 36, "3.0": 370}, |
|
118 |
+ { "month": 5, "0.0": 249, "1.0": 227, "2.0": 58, "3.0": 382}, |
|
119 |
+ { "month": 6, "0.0": 224, "1.0": 192, "2.0": 68, "3.0": 364 }, |
|
120 |
+ { "month": 7, "0.0": 263, "1.0": 220, "2.0": 68, "3.0": 292 }, |
|
121 |
+ { "month": 8, "0.0": 233, "1.0": 222, "2.0": 42, "3.0": 258}, |
|
122 |
+ { "month": 9, "0.0": 198, "1.0": 219, "2.0": 50, "3.0": 211}, |
|
123 |
+ { "month": 10, "0.0": 228, "1.0": 238, "2.0": 53, "3.0": 230 }, |
|
124 |
+ { "month": 11, "0.0": 238, "1.0": 230, "2.0": 42, "3.0": 213}, |
|
125 |
+ { "month": 12, "0.0": 206, "1.0": 219, "2.0": 30, "3.0": 235 } |
|
126 |
+ ], |
|
110 | 127 |
emptyClusterData2: [], |
111 | 128 |
clusterData2 :[ |
112 | 129 |
{ "Cluster_Labels":0.0, "mean":91.0661736084 }, |
113 | 130 |
{ "Cluster_Labels":1.0, "mean":331.3113772455 }, |
114 | 131 |
{ "Cluster_Labels":2.0, "mean":12.2679856115 }, |
115 | 132 |
{ "Cluster_Labels":3.0, "mean":123.3695111848 } |
116 |
- ], |
|
133 |
+ ], |
|
117 | 134 |
emptyClusterData3: [], |
118 | 135 |
clusterData3 :[ |
119 | 136 |
{ "Cluster_Labels":0.0, "9":787.0, "B":41.0, "D":46.0, "F":1135.0, "L":320.0, "M":200.0 }, |
... | ... | @@ -138,9 +155,11 @@ |
138 | 155 |
this.emptyNetData = this.netData; |
139 | 156 |
this.emptyLineData = this.lineData; |
140 | 157 |
this.emptyClusterData = this.clusterData; |
158 |
+ this.emptyClusterData1 = this.clusterData1; |
|
141 | 159 |
this.emptyClusterData2 = this.clusterData2; |
142 | 160 |
this.emptyClusterData3 = this.clusterData3; |
143 | 161 |
this.emptyClusterData4 = this.clusterData4; |
162 |
+ |
|
144 | 163 |
} |
145 | 164 |
}, |
146 | 165 |
watch: { |
... | ... | @@ -151,7 +170,8 @@ |
151 | 170 |
'VerticalBarChart': VerticalBarChart, |
152 | 171 |
'LineChart': LineChart, |
153 | 172 |
'DataChart1': DataChart1, |
154 |
- 'StackedColumnChart' : StackedColumnChart |
|
173 |
+ 'StackedColumnChart' : StackedColumnChart, |
|
174 |
+ 'MultiLineChart' : MultiLineChart |
|
155 | 175 |
}, |
156 | 176 |
mounted() { |
157 | 177 |
this.dataSet(); |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?