
--- client/resources/css/main.css
+++ client/resources/css/main.css
... | ... | @@ -95,6 +95,7 @@ |
95 | 95 |
border-radius: 10px; |
96 | 96 |
box-shadow: 0px 0px 10px #eee; |
97 | 97 |
padding: 30px; |
98 |
+ height: 500px; |
|
98 | 99 |
} |
99 | 100 |
|
100 | 101 |
#chartdiv{ |
+++ client/views/components/DataChart1.vue
This file is too big to display. |
+++ client/views/components/StackedColumnChart.vue
... | ... | @@ -0,0 +1,181 @@ |
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 | + xField: { | |
17 | + type: String, | |
18 | + required: true, | |
19 | + }, | |
20 | + yField: { | |
21 | + type: String, | |
22 | + required: true, | |
23 | + }, | |
24 | + color: { | |
25 | + type: Array, | |
26 | + default: ['#1c7ed6'], | |
27 | + }, | |
28 | + }, | |
29 | + data() { | |
30 | + return { | |
31 | + chart: null, | |
32 | + }; | |
33 | + }, | |
34 | + methods: { | |
35 | + createChart(data, xField, yField, color) { | |
36 | + console.log(color) | |
37 | + let chartWarp = this.$refs["chartdiv"]; // 차트 상위 div ref 매칭 | |
38 | + chartWarp.innerHTML = ""; // 차트 상위 div 내용 초기화 (기존 차트 삭제) | |
39 | + let div = document.createElement("div"); // 차트를 담을 빈 div 생성 (차트 하위 div) | |
40 | + div.style.width = "100%"; // 차트를 담을 div의 넓이 | |
41 | + div.style.height = "100%"; // 차트를 담을 div의 높이 | |
42 | + chartWarp.appendChild(div); // 차트 상위 div 안에 차트 하위 div를 추가 | |
43 | + let root = am5.Root.new(div); // 차트 하위 div에 차트(root) 담기 | |
44 | + this.charts = root; // 차트 정보 전역에 담기 | |
45 | + | |
46 | + root._logo.dispose(); | |
47 | + | |
48 | + let coulmns = Object.keys(data[0]); | |
49 | + | |
50 | + | |
51 | + | |
52 | + for(let i = 0; i < coulmns.length ; i++){ | |
53 | + if(coulmns[i] == xField){ | |
54 | + coulmns.splice(i,1); | |
55 | + } | |
56 | + | |
57 | + } | |
58 | + console.log('data',data) | |
59 | + console.log('coulmns',coulmns) | |
60 | + | |
61 | + | |
62 | + // Set themes | |
63 | + // https://www.amcharts.com/docs/v5/concepts/themes/ | |
64 | + root.setThemes([ | |
65 | + am5themes_Animated.new(root) | |
66 | + ]); | |
67 | + // Create chart | |
68 | + let chart = root.container.children.push(am5xy.XYChart.new(root, { | |
69 | + panX: false, | |
70 | + panY: false, | |
71 | + wheelX: "panX", | |
72 | + wheelY: "zoomX", | |
73 | + paddingLeft: 0, | |
74 | + layout: root.verticalLayout | |
75 | + })); | |
76 | + | |
77 | + // Add scrollbar | |
78 | + chart.set("scrollbarX", am5.Scrollbar.new(root, { | |
79 | + orientation: "horizontal" | |
80 | + })); | |
81 | + | |
82 | + // Add cursor | |
83 | + // let cursor = chart.set("cursor", am5xy.XYCursor.new(root, {})); | |
84 | + // cursor.lineY.set("visible", false); | |
85 | + | |
86 | + // Create axes | |
87 | + let xRenderer = am5xy.AxisRendererX.new(root, { minGridDistance: 30 }); | |
88 | + xRenderer.labels.template.setAll({ | |
89 | + centerY: am5.p50, | |
90 | + centerX: am5.p50, | |
91 | + }); | |
92 | + | |
93 | + xRenderer.grid.template.setAll({ | |
94 | + location: 1 | |
95 | + }); | |
96 | + | |
97 | + let xAxis = chart.xAxes.push(am5xy.CategoryAxis.new(root, { | |
98 | + maxDeviation: 0.3, | |
99 | + categoryField: xField, | |
100 | + renderer: xRenderer, | |
101 | + tooltip: am5.Tooltip.new(root, {}) | |
102 | + })); | |
103 | + | |
104 | + xAxis.data.setAll(data); | |
105 | + | |
106 | + let yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { | |
107 | + maxDeviation: 0.3, | |
108 | + min: 0, | |
109 | + renderer: am5xy.AxisRendererY.new(root, { | |
110 | + strokeOpacity: 0.1, | |
111 | + // inversed: true | |
112 | + }) | |
113 | + })); | |
114 | + | |
115 | + let legend = chart.children.push(am5.Legend.new(root, { | |
116 | + centerX: am5.p50, | |
117 | + x: am5.p50 | |
118 | + })); | |
119 | + | |
120 | + for(let s = 0 ; s < coulmns.length; s++){ | |
121 | + this.makeSeries(chart,xField, xAxis ,yAxis, root,data,legend ,coulmns[s],coulmns[s]); | |
122 | + } | |
123 | + | |
124 | + | |
125 | + chart.appear(1000, 100); | |
126 | + | |
127 | + return chart; | |
128 | + }, | |
129 | + | |
130 | + makeSeries : function(chart,xField, xAxis ,yAxis ,root ,data , legend , name, fieldName) { | |
131 | + let series = chart.series.push(am5xy.ColumnSeries.new(root, { | |
132 | + name: name, | |
133 | + stacked: true, | |
134 | + xAxis: xAxis, | |
135 | + yAxis: yAxis, | |
136 | + valueYField: fieldName, | |
137 | + categoryXField: xField | |
138 | + })); | |
139 | + | |
140 | + series.columns.template.setAll({ | |
141 | + tooltipText: "{name}, {categoryX}: {valueY}", | |
142 | + tooltipY: am5.percent(10) | |
143 | + }); | |
144 | + series.data.setAll(data); | |
145 | + | |
146 | + // Make stuff animate on load | |
147 | + // https://www.amcharts.com/docs/v5/concepts/animations/ | |
148 | + series.appear(); | |
149 | + | |
150 | + series.bullets.push(function () { | |
151 | + return am5.Bullet.new(root, { | |
152 | + sprite: am5.Label.new(root, { | |
153 | + text: "{valueY}", | |
154 | + fill: root.interfaceColors.get("alternativeText"), | |
155 | + centerY: am5.p50, | |
156 | + centerX: am5.p50, | |
157 | + populateText: true | |
158 | + }) | |
159 | + }); | |
160 | + }); | |
161 | + legend.data.push(series); | |
162 | + } | |
163 | + }, | |
164 | + watch: { | |
165 | + 'chartData': function (newData) { | |
166 | + this.createChart(newData, this.xField, this.yField, this.color); | |
167 | + } | |
168 | + }, | |
169 | + mounted() { | |
170 | + // this.chart = this.createChart(this.data, this.xField, this.yField, this.color); | |
171 | + }, | |
172 | +}; | |
173 | +</script> | |
174 | + | |
175 | +<style scoped> | |
176 | +.chart-container { | |
177 | + width: 100%; | |
178 | + height: 95%; | |
179 | +} | |
180 | +</style> | |
181 | + (No newline at end of file) |
--- client/views/components/VerticalBarChart.vue
+++ client/views/components/VerticalBarChart.vue
... | ... | @@ -57,7 +57,9 @@ |
57 | 57 |
panY: true, |
58 | 58 |
wheelX: "panX", |
59 | 59 |
wheelY: "zoomX", |
60 |
- pinchZoomX: true |
|
60 |
+ pinchZoomX: true, |
|
61 |
+ paddingLeft:0, |
|
62 |
+ paddingRight:1 |
|
61 | 63 |
})); |
62 | 64 |
|
63 | 65 |
// Add cursor |
... | ... | @@ -87,7 +89,7 @@ |
87 | 89 |
min: 0, |
88 | 90 |
renderer: am5xy.AxisRendererY.new(root, { |
89 | 91 |
strokeOpacity: 0.1, |
90 |
- inversed: true |
|
92 |
+ // inversed: true |
|
91 | 93 |
}) |
92 | 94 |
})); |
93 | 95 |
|
... | ... | @@ -152,7 +154,7 @@ |
152 | 154 |
<style scoped> |
153 | 155 |
.chart-container { |
154 | 156 |
width: 100%; |
155 |
- height: 300px; |
|
157 |
+ height: 95%; |
|
156 | 158 |
} |
157 | 159 |
</style> |
158 | 160 |
(No newline at end of file) |
--- client/views/pages/Main/Main.vue
+++ client/views/pages/Main/Main.vue
... | ... | @@ -10,40 +10,50 @@ |
10 | 10 |
<div class="content-box"> |
11 | 11 |
<div class="chart-title"> |
12 | 12 |
<div class="flex"> |
13 |
- <p>월별 평균 길이 Z축 마모</p> |
|
14 |
- <select name="" id=""> |
|
15 |
- <option v-for="(tool, index) in tools" :key="index" :value="tool">{{ tool }}</option> |
|
16 |
- </select> |
|
13 |
+ <p>정비 주기 패턴 군집</p> |
|
17 | 14 |
</div> |
18 | 15 |
</div> |
19 |
- <VerticalBarChart :chartData="emptyData" xField="month" yField="value" /> |
|
16 |
+ <DataChart1 :chartData="emptyLineData" :keyMapping="lineDataKeyMapping" :xField="lineDataKeyMapping.date" /> |
|
20 | 17 |
</div> |
21 | 18 |
<div class="content-box"> |
22 | 19 |
<div class="chart-title"> |
23 | 20 |
<div class="flex"> |
24 |
- <p>시간대별 평균 길이 Z축 마모</p> |
|
25 |
- <select name="" id=""> |
|
26 |
- <option v-for="(tool, index) in tools" :key="index" :value="tool">{{ tool }}</option> |
|
27 |
- </select> |
|
21 |
+ <p>군집/월별 점검 횟수</p> |
|
28 | 22 |
</div> |
29 | 23 |
</div> |
30 |
- <VerticalBarChart :chartData="emptyTimeData" :xField="'time'" :yField="'value'" :color="['#1c7ed6','#74c0fc','#1864ab']" /> |
|
24 |
+ <!-- <VerticalBarChart :chartData="emptyTimeData" :xField="'time'" :yField="'mean'" :color="['#1c7ed6','#74c0fc','#1864ab']" /> --> |
|
31 | 25 |
</div> |
32 | 26 |
<div class="content-box"> |
33 | 27 |
<div class="chart-title"> |
34 | 28 |
<div> |
35 |
- <p>가동시간에 따른 각 툴별(도구) 길이 Z축 마모</p> |
|
29 |
+ <p>군집별 평균 주행거리</p> |
|
36 | 30 |
</div> |
37 | 31 |
</div> |
38 |
- <LineChart :chartData="emptyLineData" :keyMapping="lineDataKeyMapping" :xField="lineDataKeyMapping.date" /> |
|
32 |
+ <VerticalBarChart :chartData="emptyClusterData" :xField="'Cluster_Labels'" :yField="'mean'" :color="['#1c7ed6','#74c0fc','#1864ab']" /> |
|
39 | 33 |
</div> |
40 | 34 |
<div class="content-box"> |
41 | 35 |
<div class="chart-title"> |
42 | 36 |
<div> |
43 |
- <p>가동시간에 따른 각 툴별(도구) 길이 X축 형상마모</p> |
|
37 |
+ <p>군집별 평균정비 주기</p> |
|
44 | 38 |
</div> |
45 | 39 |
</div> |
46 |
- <LineChart :chartData="emptyLineData" :keyMapping="lineDataKeyMapping" :xField="lineDataKeyMapping.date" /> |
|
40 |
+ <VerticalBarChart :chartData="emptyClusterData2" :xField="'Cluster_Labels'" :yField="'mean'" :color="['#1c7ed6','#74c0fc','#1864ab']" /> |
|
41 |
+ </div> |
|
42 |
+ <div class="content-box"> |
|
43 |
+ <div class="chart-title"> |
|
44 |
+ <div> |
|
45 |
+ <p>군집별 차종 현황</p> |
|
46 |
+ </div> |
|
47 |
+ </div> |
|
48 |
+ <StackedColumnChart :chartData="emptyClusterData3" :xField="'Cluster_Labels'" /> |
|
49 |
+ </div> |
|
50 |
+ <div class="content-box"> |
|
51 |
+ <div class="chart-title"> |
|
52 |
+ <div> |
|
53 |
+ <p>군집별 제조사 현황</p> |
|
54 |
+ </div> |
|
55 |
+ </div> |
|
56 |
+ <StackedColumnChart :chartData="emptyClusterData4" :xField="'Cluster_Labels'" /> |
|
47 | 57 |
</div> |
48 | 58 |
</div> |
49 | 59 |
</div> |
... | ... | @@ -52,6 +62,9 @@ |
52 | 62 |
<script> |
53 | 63 |
import VerticalBarChart from '../../components/VerticalBarChart.vue'; |
54 | 64 |
import LineChart from '../../components/LineChart.vue'; |
65 |
+import DataChart1 from '../../components/DataChart1.vue'; |
|
66 |
+import StackedColumnChart from '../../components/StackedColumnChart.vue'; |
|
67 |
+ |
|
55 | 68 |
|
56 | 69 |
export default { |
57 | 70 |
data() { |
... | ... | @@ -86,7 +99,36 @@ |
86 | 99 |
{ date: "2023-01-01", value1: 10, value2: 20, value3: 50 }, |
87 | 100 |
{ date: "2023-01-02", value1: 15, value2: 25, value3: 50 }, |
88 | 101 |
{ date: "2023-01-03", value1: 20, value2: 30, value3: 50 }, |
89 |
- ] |
|
102 |
+ ], |
|
103 |
+ emptyClusterData: [], |
|
104 |
+ clusterData : [ |
|
105 |
+ { Cluster_Labels:0.0, mean:242.8801507382 }, |
|
106 |
+ { Cluster_Labels:1.0, mean:90.112943153}, |
|
107 |
+ { Cluster_Labels:2.0, mean:158.4532030077}, |
|
108 |
+ { Cluster_Labels:3.0, mean:60.4299174302 }, |
|
109 |
+ ], |
|
110 |
+ emptyClusterData2: [], |
|
111 |
+ clusterData2 :[ |
|
112 |
+ { "Cluster_Labels":0.0, "mean":91.0661736084 }, |
|
113 |
+ { "Cluster_Labels":1.0, "mean":331.3113772455 }, |
|
114 |
+ { "Cluster_Labels":2.0, "mean":12.2679856115 }, |
|
115 |
+ { "Cluster_Labels":3.0, "mean":123.3695111848 } |
|
116 |
+ ], |
|
117 |
+ emptyClusterData3: [], |
|
118 |
+ clusterData3 :[ |
|
119 |
+ { "Cluster_Labels":0.0, "9":787.0, "B":41.0, "D":46.0, "F":1135.0, "L":320.0, "M":200.0 }, |
|
120 |
+ { "Cluster_Labels":1.0, "9":386.0, "B":105.0, "D":250.0, "F":831.0, "L":329.0, "M":459.0 }, |
|
121 |
+ { "Cluster_Labels":2.0, "9":314.0, "B":8.0, "D":34.0, "F":103.0, "L":34.0, "M":29.0 }, |
|
122 |
+ { "Cluster_Labels":3.0, "9":297.0, "B":257.0, "D":380.0, "F":1152.0, "L":495.0, "M":667.0 } |
|
123 |
+ ], |
|
124 |
+ emptyClusterData4: [], |
|
125 |
+ clusterData4 :[ |
|
126 |
+ { "Cluster_Labels":0.0, "B":40.0, "D":786.0, "M":1501.0, "N":241.0 }, |
|
127 |
+ { "Cluster_Labels":1.0, "B":332.0, "D":394.0, "M":1381.0,"N":564.0 }, |
|
128 |
+ { "Cluster_Labels":2.0, "B":41.0, "D":314.0, "M":164.0, "N":37.0 }, |
|
129 |
+ { "Cluster_Labels":3.0, "B":399.0, "D":305.0, "M":1992.0, "N":924.0} |
|
130 |
+ ], |
|
131 |
+ |
|
90 | 132 |
} |
91 | 133 |
}, |
92 | 134 |
methods: { |
... | ... | @@ -95,6 +137,10 @@ |
95 | 137 |
this.emptyTimeData = this.timeData; |
96 | 138 |
this.emptyNetData = this.netData; |
97 | 139 |
this.emptyLineData = this.lineData; |
140 |
+ this.emptyClusterData = this.clusterData; |
|
141 |
+ this.emptyClusterData2 = this.clusterData2; |
|
142 |
+ this.emptyClusterData3 = this.clusterData3; |
|
143 |
+ this.emptyClusterData4 = this.clusterData4; |
|
98 | 144 |
} |
99 | 145 |
}, |
100 | 146 |
watch: { |
... | ... | @@ -103,7 +149,9 @@ |
103 | 149 |
computed: {}, |
104 | 150 |
components: { |
105 | 151 |
'VerticalBarChart': VerticalBarChart, |
106 |
- 'LineChart': LineChart |
|
152 |
+ 'LineChart': LineChart, |
|
153 |
+ 'DataChart1': DataChart1, |
|
154 |
+ 'StackedColumnChart' : StackedColumnChart |
|
107 | 155 |
}, |
108 | 156 |
mounted() { |
109 | 157 |
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?