@operato/scene-gauge 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/@types/global/index.d.ts +1 -0
  2. package/CHANGELOG.md +16 -0
  3. package/LICENSE +21 -0
  4. package/README.md +15 -0
  5. package/assets/gauge-circle.png +0 -0
  6. package/assets/gauge-horizontal.png +0 -0
  7. package/assets/gauge-vertical.png +0 -0
  8. package/dist/gauge-circle.d.ts +57 -0
  9. package/dist/gauge-circle.js +211 -0
  10. package/dist/gauge-circle.js.map +1 -0
  11. package/dist/gauge-horizon.d.ts +56 -0
  12. package/dist/gauge-horizon.js +145 -0
  13. package/dist/gauge-horizon.js.map +1 -0
  14. package/dist/gauge-properties.d.ts +39 -0
  15. package/dist/gauge-properties.js +114 -0
  16. package/dist/gauge-properties.js.map +1 -0
  17. package/dist/gauge-vertical.d.ts +56 -0
  18. package/dist/gauge-vertical.js +143 -0
  19. package/dist/gauge-vertical.js.map +1 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.js +7 -0
  22. package/dist/index.js.map +1 -0
  23. package/helps/scene/component/gauge-circle.ko.md +168 -0
  24. package/helps/scene/component/gauge-circle.md +167 -0
  25. package/helps/scene/component/gauge-circle.zh.md +164 -0
  26. package/helps/scene/component/gauge-horizon.ko.md +145 -0
  27. package/helps/scene/component/gauge-horizon.md +145 -0
  28. package/helps/scene/component/gauge-horizon.zh.md +145 -0
  29. package/helps/scene/component/gauge-vertical.ko.md +12 -0
  30. package/helps/scene/component/gauge-vertical.md +9 -0
  31. package/helps/scene/component/gauge-vertical.zh.md +10 -0
  32. package/helps/scene/images/gauge-circle-01.png +0 -0
  33. package/helps/scene/images/gauge-circle-02.png +0 -0
  34. package/helps/scene/images/gauge-circle-03.png +0 -0
  35. package/helps/scene/images/gauge-circle-04.png +0 -0
  36. package/helps/scene/images/gauge-circle-05.png +0 -0
  37. package/helps/scene/images/gauge-circle-06.png +0 -0
  38. package/helps/scene/images/gauge-circle-07.png +0 -0
  39. package/helps/scene/images/gauge-circle-08.png +0 -0
  40. package/helps/scene/images/gauge-circle-09.png +0 -0
  41. package/helps/scene/images/gauge-circle-10.png +0 -0
  42. package/helps/scene/images/gauge-circle-11.png +0 -0
  43. package/helps/scene/images/gauge-circle-12.png +0 -0
  44. package/helps/scene/images/gauge-circle-13.png +0 -0
  45. package/helps/scene/images/gauge-circle-14.png +0 -0
  46. package/helps/scene/images/gauge-circle-15.png +0 -0
  47. package/helps/scene/images/gauge-circle-16.png +0 -0
  48. package/helps/scene/images/gauge-circle-17.png +0 -0
  49. package/helps/scene/images/gauge-circle-18.png +0 -0
  50. package/helps/scene/images/gauge-circle-19.png +0 -0
  51. package/helps/scene/images/gauge-circle-20.png +0 -0
  52. package/helps/scene/images/gauge-circle-21.png +0 -0
  53. package/helps/scene/images/gauge-horizontal-01.png +0 -0
  54. package/helps/scene/images/gauge-vertical-01.png +0 -0
  55. package/helps/scene/images/gauge-vertical-02.png +0 -0
  56. package/helps/scene/images/gauge-vertical-03.png +0 -0
  57. package/helps/scene/images/gauge-vertical-04.png +0 -0
  58. package/helps/scene/images/gauge-vertical-05.png +0 -0
  59. package/helps/scene/images/gauge-vertical-06.png +0 -0
  60. package/helps/scene/images/gauge-vertical-07.png +0 -0
  61. package/helps/scene/images/gauge-vertical-08.png +0 -0
  62. package/helps/scene/images/gauge-vertical-09.png +0 -0
  63. package/helps/scene/images/gauge-vertical-10.png +0 -0
  64. package/helps/scene/images/gauge-vertical-11.png +0 -0
  65. package/helps/scene/images/gauge-vertical-12.png +0 -0
  66. package/helps/scene/images/gauge-vertical-13.png +0 -0
  67. package/helps/scene/images/gauge-vertical-14.png +0 -0
  68. package/helps/scene/images/gauge-vertical-15.png +0 -0
  69. package/helps/scene/images/gauge-vertical-16.png +0 -0
  70. package/helps/scene/images/gauge-vertical-17.png +0 -0
  71. package/helps/scene/images/gauge-vertical-18.png +0 -0
  72. package/package.json +61 -0
  73. package/src/gauge-circle.ts +310 -0
  74. package/src/gauge-horizon.ts +204 -0
  75. package/src/gauge-properties.ts +114 -0
  76. package/src/gauge-vertical.ts +203 -0
  77. package/src/index.ts +6 -0
  78. package/test/basic-test.html +67 -0
  79. package/test/index.html +22 -0
  80. package/things-scene.config.js +158 -0
  81. package/translations/en.json +3 -0
  82. package/translations/ko.json +3 -0
  83. package/translations/ms.json +3 -0
  84. package/translations/zh.json +3 -0
  85. package/tsconfig.json +22 -0
  86. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1 @@
1
+ declare module '*.png'
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ### [0.0.16](https://github.com/things-scene/operato-scene/compare/v0.0.15...v0.0.16) (2021-12-09)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * add indoor-map and gauge component ([35d8a75](https://github.com/things-scene/operato-scene/commit/35d8a75f7d691dd23ea299fd772b79d19eec5d2f))
12
+
13
+
14
+ ### :bug: Bug Fix
15
+
16
+ * upgrade [@operato](https://github.com/operato) dependencies ([92985c7](https://github.com/things-scene/operato-scene/commit/92985c76d2b7e6d3941c2c809a85b3676a579b0e))
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Hearty, Oh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # things-scene-gauge
2
+
3
+ ## build
4
+
5
+ `$ yarn build`
6
+
7
+ | type | filename | for | tested |
8
+ | ---- | ------------------------ | -------------- | ------ |
9
+ | UMD | things-scene-gauge.js | modern browser | O |
10
+ | UMD | things-scene-gauge-ie.js | ie 11 | O |
11
+ | ESM | things-scene-gauge.mjs | modern browser | O |
12
+
13
+ ## publish
14
+
15
+ `$ yarn publish`
Binary file
Binary file
Binary file
@@ -0,0 +1,57 @@
1
+ import { Donut } from '@hatiolab/things-scene';
2
+ declare const GaugeCircle_base: (new (...args: any[]) => {
3
+ value: number;
4
+ animValue: number;
5
+ animOnValueChange(value: number, animFromBase: boolean, base: number): void;
6
+ }) & typeof Donut;
7
+ export default class GaugeCircle extends GaugeCircle_base {
8
+ _draw(context: CanvasRenderingContext2D): void;
9
+ contains(x: number, y: number): boolean;
10
+ _post_draw(context: CanvasRenderingContext2D): void;
11
+ get nature(): {
12
+ mutable: boolean;
13
+ resizable: boolean;
14
+ rotatable: boolean;
15
+ properties: ({
16
+ type: string;
17
+ label: string;
18
+ name: string;
19
+ property: string;
20
+ observe?: undefined;
21
+ } | {
22
+ type: string;
23
+ label: string;
24
+ name: string;
25
+ observe: (this: HTMLElement, startValue: number) => void;
26
+ property: string;
27
+ } | {
28
+ type: string;
29
+ label: string;
30
+ name: string;
31
+ property: {
32
+ min: number;
33
+ max: number;
34
+ label?: undefined;
35
+ };
36
+ observe?: undefined;
37
+ } | {
38
+ type: string;
39
+ label: string;
40
+ name: string;
41
+ property: {
42
+ label: string;
43
+ min?: undefined;
44
+ max?: undefined;
45
+ };
46
+ observe?: undefined;
47
+ } | {
48
+ type: string;
49
+ label: string;
50
+ name: string;
51
+ property?: undefined;
52
+ observe?: undefined;
53
+ })[];
54
+ help: string;
55
+ };
56
+ }
57
+ export {};
@@ -0,0 +1,211 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { Component, Donut, ValueHolder } from '@hatiolab/things-scene';
5
+ import { PROPERTIES } from './gauge-properties';
6
+ const NATURE = {
7
+ mutable: false,
8
+ resizable: true,
9
+ rotatable: true,
10
+ properties: [
11
+ ...PROPERTIES,
12
+ {
13
+ type: 'number',
14
+ label: 'start-angle',
15
+ name: 'startAngle',
16
+ property: 'startAngle'
17
+ },
18
+ {
19
+ type: 'number',
20
+ label: 'end-angle',
21
+ name: 'endAngle',
22
+ property: 'endAngle'
23
+ },
24
+ {
25
+ type: 'color',
26
+ label: 'text-fill-style',
27
+ name: 'textFillStyle',
28
+ property: 'textFillStyle'
29
+ },
30
+ {
31
+ type: 'color',
32
+ label: 'needle-fill-style',
33
+ name: 'needleFillStyle',
34
+ property: 'needleFillStyle'
35
+ },
36
+ {
37
+ type: 'color',
38
+ label: 'inner-circle-fill-style',
39
+ name: 'innerCircleFillStyle',
40
+ property: 'innerCircleFillStyle'
41
+ },
42
+ {
43
+ type: 'checkbox',
44
+ label: 'in-text',
45
+ name: 'inText',
46
+ property: 'inText'
47
+ }
48
+ ],
49
+ help: 'scene/component/gauge-circle'
50
+ };
51
+ function drawStepLine(context, ang, rx, stepNeedleSize) {
52
+ context.rotate(ang);
53
+ context.translate(0, -rx);
54
+ context.fillRect(0, -rx * 0.14, stepNeedleSize, rx * 0.175);
55
+ context.translate(0, rx);
56
+ context.rotate(-ang);
57
+ }
58
+ function drawSubStepLine(context, ang, rx, stepNeedleSize) {
59
+ context.rotate(ang);
60
+ context.translate(0, -rx);
61
+ context.fillRect(0, -rx * 0.04, stepNeedleSize, rx * 0.075);
62
+ context.translate(0, rx);
63
+ context.rotate(-ang);
64
+ }
65
+ function drawStepText(context, text, ang, rx) {
66
+ context.rotate(ang);
67
+ context.translate(0, -rx * 0.83);
68
+ context.rotate(-ang);
69
+ context.fillText(text, 0, 0);
70
+ context.rotate(ang);
71
+ context.translate(0, rx * 0.83);
72
+ context.rotate(-ang);
73
+ }
74
+ function drawNeedle(context, rx, ang) {
75
+ context.rotate(ang);
76
+ context.beginPath();
77
+ context.moveTo(rx * 0.035, 0); // 중앙 두께
78
+ context.lineTo(0, rx * 0.8); // 끝 점
79
+ context.lineTo(-rx * 0.035, 0); // 중앙 두께
80
+ context.lineTo(-rx * 0.015, -rx * 0.2); // 뒷쪽 두께
81
+ context.lineTo(rx * 0.015, -rx * 0.2); // 뒷쪽 두께
82
+ context.rotate(-ang);
83
+ }
84
+ export default class GaugeCircle extends ValueHolder(Donut) {
85
+ _draw(context) {
86
+ var { lineWidth = 20, startValue, endValue, step, subStep, startAngle = 0, endAngle = 180, fontColor = 'black', showStepText = true, showStartValue = true, showEndValue = true, showStepLine = true, showSubStep = true, inText = true, colorStops, // 스텝별 각각 다른 색
87
+ fillStyle, textFillStyle = 'black', needleFillStyle = 'black', innerCircleFillStyle = 'gray', stepNeedleSize = 2, stepFillStyle, stepTextSize, cx, cy, rx, ry, ratio, animFromBase = false } = this.model;
88
+ startValue = Number(startValue);
89
+ this.animOnValueChange(this.value, animFromBase, startValue);
90
+ const RADIAN = 0.0174533 / Math.PI;
91
+ const rxRatio = (rx / 100) * ratio; // 원 안에 지워지는 비율을 계산한 rx - ratio의 비율에 따라 크기가 변함
92
+ const ryRatio = (ry / 100) * ratio; // 원 안에 지워지는 비율을 계산한 ry - ratio의 비율에 따라 크기가 변함
93
+ const circleSize = (endAngle - startAngle) / 180; // 원의 총 길이. - PI * 2가 원이므로 (360도 = 2, 180도 = 1)
94
+ const totalValue = endValue - startValue; // 게이지의 시작과 끝 값의 크기
95
+ startAngle = startAngle * RADIAN - 0.5; // 맨 위쪽을 중심으로 앵글의 범위에 따라 왼쪽으로 넓어짐
96
+ endAngle = endAngle * RADIAN - 0.5; // 맨 위쪽을 중심으로 앵글의 범위에 따라 오른쪽으로 넓어짐
97
+ context.translate(cx, cy);
98
+ //// 메인 게이지 원 그리기 ////
99
+ context.beginPath();
100
+ context.ellipse(0, 0, Math.abs(rx), Math.abs(ry), 0, startAngle * Math.PI, endAngle * Math.PI);
101
+ this.drawStroke(context);
102
+ context.ellipse(0, 0, Math.abs(rxRatio), Math.abs(ryRatio), 0, endAngle * Math.PI, startAngle * Math.PI, true); // 반대로 그리며 원을 지움.
103
+ // this.drawFill(context)
104
+ context.closePath();
105
+ //// 스텝별 색 칠하기 ////
106
+ if (colorStops) {
107
+ let beforeValue = 0;
108
+ let endStepAngle = 0;
109
+ context.moveTo(0, 0);
110
+ colorStops.forEach(function (v, idx, arr) {
111
+ context.beginPath();
112
+ let value = Math.max(Math.min(v.position - startValue, totalValue), 0); // v.position 범위의 최소값은 0, 최대값은 totalValue가 되야함.
113
+ let startStepAngle = endStepAngle || Math.PI * (startAngle + (circleSize * beforeValue) / totalValue);
114
+ if (idx === arr.length - 1)
115
+ // 마지막값은 무조건 끝까지 채워주도록 한다
116
+ endStepAngle = Math.PI * (startAngle + circleSize);
117
+ else
118
+ endStepAngle = Math.PI * (startAngle + (circleSize * value) / totalValue);
119
+ if (beforeValue > totalValue || beforeValue > value)
120
+ // 값이 게이지의 최대 값을 넘어가거나 이전 값 보다 현재값이 작으면 다시 그릴 필요 없음
121
+ return false;
122
+ context.ellipse(0, 0, Math.abs(rx), Math.abs(ry), 0, startStepAngle, endStepAngle);
123
+ context.ellipse(0, 0, Math.abs(rxRatio), Math.abs(ryRatio), 0, endStepAngle, startStepAngle, true);
124
+ context.fillStyle = v.color;
125
+ context.fill();
126
+ beforeValue = value;
127
+ });
128
+ }
129
+ context.scale(1, ry / rx);
130
+ //// 바늘 그리기 ////
131
+ context.beginPath();
132
+ let drawingValue = this.animValue;
133
+ drawingValue = Math.max(Math.min(drawingValue, endValue), startValue); // 그려지는 값은 startValue보다 작을 수 없고, endValue보다 클 수 없음.
134
+ let ang = Math.PI * ((circleSize * (drawingValue - startValue)) / totalValue + startAngle - 0.5);
135
+ drawNeedle(context, rx, ang);
136
+ context.fillStyle = needleFillStyle;
137
+ context.fill();
138
+ //// 중앙 원 그리기 ////
139
+ context.beginPath();
140
+ context.ellipse(0, 0, Math.abs(rx) / 15, Math.abs(rx) / 15, 0, 0, 2 * Math.PI);
141
+ context.fillStyle = innerCircleFillStyle;
142
+ context.fill();
143
+ //// 스텝 선 그리기 ////
144
+ context.fillStyle = stepFillStyle;
145
+ if (showStepLine) {
146
+ let count = totalValue / step;
147
+ // Draw StartValue
148
+ drawStepLine(context, Math.PI * (startAngle + 0.5), rx * 0.8, stepNeedleSize); // 원을 그릴때 PI는 45도 부터 그리지만 angle은 0도부터 틀어서 + 0.5도를 곱해줘야함
149
+ // Draw StepValue
150
+ for (let num = 1; num < count; num++) {
151
+ let ang = Math.PI * ((circleSize / count) * num + startAngle + 0.5);
152
+ drawStepLine(context, ang, rx * 0.8, stepNeedleSize);
153
+ }
154
+ // Draw EndValue
155
+ drawStepLine(context, Math.PI * (endAngle + 0.5), rx * 0.8, stepNeedleSize);
156
+ }
157
+ //// 서브 스탭 그리기 ////
158
+ if (showSubStep) {
159
+ let count = totalValue;
160
+ // Draw StepValue
161
+ for (let num = 1; num <= count; num++) {
162
+ if (num % step == 0 || num % subStep != 0) {
163
+ // 메인 스탭과 서브 스탭은 그리지 않음
164
+ continue;
165
+ }
166
+ let ang = Math.PI * ((circleSize / count) * num + startAngle + 0.5);
167
+ drawSubStepLine(context, ang, rx * 0.8, stepNeedleSize);
168
+ }
169
+ }
170
+ //// 스텝 텍스트 그리기 ////
171
+ context.fillStyle = textFillStyle;
172
+ context.font = (rx * stepTextSize) / 50 + 'px arial';
173
+ context.textBaseline = 'middle';
174
+ context.textAlign = 'center';
175
+ let textLocation = inText ? 0.8 : 1.35;
176
+ if (showStartValue) {
177
+ // Draw StartText
178
+ drawStepText(context, startValue, Math.PI * (startAngle + 0.5), rx * textLocation);
179
+ }
180
+ if (showEndValue) {
181
+ // Draw EndText
182
+ drawStepText(context, endValue, Math.PI * (endAngle + 0.5), rx * textLocation);
183
+ }
184
+ if (showStepText) {
185
+ // Draw StepText
186
+ let count = totalValue / step;
187
+ for (let num = 1; num < count; num++) {
188
+ let value = startValue + step * num;
189
+ let ang = Math.PI * ((circleSize / count) * num + startAngle + 0.5);
190
+ drawStepText(context, value, ang, rx * textLocation);
191
+ }
192
+ }
193
+ context.scale(1, rx / ry);
194
+ context.translate(-cx, -cy);
195
+ }
196
+ contains(x, y) {
197
+ // 컨테인즈는 Ellipse로 정의함
198
+ var { cx, cy, rx, ry } = this.model;
199
+ var normx = (x - cx) / (rx * 2 - 0.5);
200
+ var normy = (y - cy) / (ry * 2 - 0.5);
201
+ return normx * normx + normy * normy < 0.25;
202
+ }
203
+ _post_draw(context) {
204
+ this.drawText(context);
205
+ }
206
+ get nature() {
207
+ return NATURE;
208
+ }
209
+ }
210
+ Component.register('gauge-circle', GaugeCircle);
211
+ //# sourceMappingURL=gauge-circle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gauge-circle.js","sourceRoot":"","sources":["../src/gauge-circle.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport { Component, Donut, ValueHolder } from '@hatiolab/things-scene';\n\nimport { PROPERTIES } from './gauge-properties';\n\nconst NATURE = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...PROPERTIES,\n {\n type: 'number',\n label: 'start-angle',\n name: 'startAngle',\n property: 'startAngle'\n },\n {\n type: 'number',\n label: 'end-angle',\n name: 'endAngle',\n property: 'endAngle'\n },\n {\n type: 'color',\n label: 'text-fill-style',\n name: 'textFillStyle',\n property: 'textFillStyle'\n },\n {\n type: 'color',\n label: 'needle-fill-style',\n name: 'needleFillStyle',\n property: 'needleFillStyle'\n },\n {\n type: 'color',\n label: 'inner-circle-fill-style',\n name: 'innerCircleFillStyle',\n property: 'innerCircleFillStyle'\n },\n {\n type: 'checkbox',\n label: 'in-text',\n name: 'inText',\n property: 'inText'\n }\n ],\n help: 'scene/component/gauge-circle'\n}\n\nfunction drawStepLine(context: CanvasRenderingContext2D, ang: number, rx: number, stepNeedleSize: number) {\n context.rotate(ang)\n context.translate(0, -rx)\n\n context.fillRect(0, -rx * 0.14, stepNeedleSize, rx * 0.175)\n context.translate(0, rx)\n context.rotate(-ang)\n}\n\nfunction drawSubStepLine(context: CanvasRenderingContext2D, ang: number, rx: number, stepNeedleSize: number) {\n context.rotate(ang)\n context.translate(0, -rx)\n\n context.fillRect(0, -rx * 0.04, stepNeedleSize, rx * 0.075)\n context.translate(0, rx)\n context.rotate(-ang)\n}\n\nfunction drawStepText(context: CanvasRenderingContext2D, text: string, ang: number, rx: number) {\n context.rotate(ang)\n context.translate(0, -rx * 0.83)\n context.rotate(-ang)\n\n context.fillText(text, 0, 0)\n context.rotate(ang)\n context.translate(0, rx * 0.83)\n context.rotate(-ang)\n}\n\nfunction drawNeedle(context: CanvasRenderingContext2D, rx: number, ang: number) {\n context.rotate(ang)\n\n context.beginPath()\n\n context.moveTo(rx * 0.035, 0) // 중앙 두께\n\n context.lineTo(0, rx * 0.8) // 끝 점\n\n context.lineTo(-rx * 0.035, 0) // 중앙 두께\n\n context.lineTo(-rx * 0.015, -rx * 0.2) // 뒷쪽 두께\n context.lineTo(rx * 0.015, -rx * 0.2) // 뒷쪽 두께\n\n context.rotate(-ang)\n}\n\nexport default class GaugeCircle extends ValueHolder(Donut) {\n _draw(context: CanvasRenderingContext2D) {\n var {\n lineWidth = 20,\n startValue,\n endValue,\n step,\n subStep,\n startAngle = 0,\n endAngle = 180,\n fontColor = 'black',\n showStepText = true,\n showStartValue = true,\n showEndValue = true,\n showStepLine = true,\n showSubStep = true,\n inText = true,\n colorStops, // 스텝별 각각 다른 색\n fillStyle,\n textFillStyle = 'black',\n needleFillStyle = 'black',\n innerCircleFillStyle = 'gray',\n stepNeedleSize = 2,\n stepFillStyle,\n stepTextSize,\n cx,\n cy,\n rx,\n ry,\n ratio,\n animFromBase = false\n } = this.model\n\n startValue = Number(startValue)\n\n this.animOnValueChange(this.value, animFromBase, startValue)\n\n const RADIAN = 0.0174533 / Math.PI\n const rxRatio = (rx / 100) * ratio // 원 안에 지워지는 비율을 계산한 rx - ratio의 비율에 따라 크기가 변함\n const ryRatio = (ry / 100) * ratio // 원 안에 지워지는 비율을 계산한 ry - ratio의 비율에 따라 크기가 변함\n const circleSize = (endAngle - startAngle) / 180 // 원의 총 길이. - PI * 2가 원이므로 (360도 = 2, 180도 = 1)\n const totalValue = endValue - startValue // 게이지의 시작과 끝 값의 크기\n\n startAngle = startAngle * RADIAN - 0.5 // 맨 위쪽을 중심으로 앵글의 범위에 따라 왼쪽으로 넓어짐\n endAngle = endAngle * RADIAN - 0.5 // 맨 위쪽을 중심으로 앵글의 범위에 따라 오른쪽으로 넓어짐\n\n context.translate(cx, cy)\n\n //// 메인 게이지 원 그리기 ////\n context.beginPath()\n\n context.ellipse(\n 0,\n 0,\n Math.abs(rx),\n Math.abs(ry),\n 0,\n startAngle * Math.PI,\n endAngle * Math.PI\n )\n this.drawStroke(context)\n context.ellipse(\n 0,\n 0,\n Math.abs(rxRatio),\n Math.abs(ryRatio),\n 0,\n endAngle * Math.PI,\n startAngle * Math.PI,\n true\n ) // 반대로 그리며 원을 지움.\n // this.drawFill(context)\n\n context.closePath()\n\n //// 스텝별 색 칠하기 ////\n if (colorStops) {\n let beforeValue = 0\n let endStepAngle = 0\n context.moveTo(0, 0)\n\n colorStops.forEach(function (v: {position: number; color: string;}, idx: number, arr: {position: number; color: string;}[]) {\n context.beginPath()\n\n let value = Math.max(Math.min(v.position - startValue, totalValue), 0) // v.position 범위의 최소값은 0, 최대값은 totalValue가 되야함.\n let startStepAngle = endStepAngle || Math.PI * (startAngle + (circleSize * beforeValue) / totalValue)\n\n if (idx === arr.length - 1)\n // 마지막값은 무조건 끝까지 채워주도록 한다\n endStepAngle = Math.PI * (startAngle + circleSize)\n else endStepAngle = Math.PI * (startAngle + (circleSize * value) / totalValue)\n\n if (beforeValue > totalValue || beforeValue > value)\n // 값이 게이지의 최대 값을 넘어가거나 이전 값 보다 현재값이 작으면 다시 그릴 필요 없음\n return false\n\n context.ellipse(0, 0, Math.abs(rx), Math.abs(ry), 0, startStepAngle, endStepAngle)\n context.ellipse(0, 0, Math.abs(rxRatio), Math.abs(ryRatio), 0, endStepAngle, startStepAngle, true)\n context.fillStyle = v.color\n context.fill()\n\n beforeValue = value\n })\n }\n context.scale(1, ry / rx)\n\n //// 바늘 그리기 ////\n context.beginPath()\n let drawingValue = this.animValue\n drawingValue = Math.max(Math.min(drawingValue, endValue), startValue) // 그려지는 값은 startValue보다 작을 수 없고, endValue보다 클 수 없음.\n\n let ang = Math.PI * ((circleSize * (drawingValue - startValue)) / totalValue + startAngle - 0.5)\n\n drawNeedle(context, rx, ang)\n\n context.fillStyle = needleFillStyle\n context.fill()\n\n //// 중앙 원 그리기 ////\n context.beginPath()\n context.ellipse(0, 0, Math.abs(rx) / 15, Math.abs(rx) / 15, 0, 0, 2 * Math.PI)\n context.fillStyle = innerCircleFillStyle\n context.fill()\n\n //// 스텝 선 그리기 ////\n context.fillStyle = stepFillStyle\n if (showStepLine) {\n let count = totalValue / step\n\n // Draw StartValue\n drawStepLine(context, Math.PI * (startAngle + 0.5), rx * 0.8, stepNeedleSize) // 원을 그릴때 PI는 45도 부터 그리지만 angle은 0도부터 틀어서 + 0.5도를 곱해줘야함\n // Draw StepValue\n for (let num = 1; num < count; num++) {\n let ang = Math.PI * ((circleSize / count) * num + startAngle + 0.5)\n\n drawStepLine(context, ang, rx * 0.8, stepNeedleSize)\n }\n // Draw EndValue\n drawStepLine(context, Math.PI * (endAngle + 0.5), rx * 0.8, stepNeedleSize)\n }\n\n //// 서브 스탭 그리기 ////\n if (showSubStep) {\n let count = totalValue\n\n // Draw StepValue\n for (let num = 1; num <= count; num++) {\n if (num % step == 0 || num % subStep != 0) {\n // 메인 스탭과 서브 스탭은 그리지 않음\n continue\n }\n let ang = Math.PI * ((circleSize / count) * num + startAngle + 0.5)\n\n drawSubStepLine(context, ang, rx * 0.8, stepNeedleSize)\n }\n }\n\n //// 스텝 텍스트 그리기 ////\n context.fillStyle = textFillStyle\n context.font = (rx * stepTextSize) / 50 + 'px arial'\n context.textBaseline = 'middle'\n context.textAlign = 'center'\n let textLocation = inText ? 0.8 : 1.35\n\n if (showStartValue) {\n // Draw StartText\n drawStepText(context, startValue, Math.PI * (startAngle + 0.5), rx * textLocation)\n }\n\n if (showEndValue) {\n // Draw EndText\n drawStepText(context, endValue, Math.PI * (endAngle + 0.5), rx * textLocation)\n }\n\n if (showStepText) {\n // Draw StepText\n let count = totalValue / step\n\n for (let num = 1; num < count; num++) {\n let value = startValue + step * num\n let ang = Math.PI * ((circleSize / count) * num + startAngle + 0.5)\n\n drawStepText(context, value, ang, rx * textLocation)\n }\n }\n\n context.scale(1, rx / ry)\n context.translate(-cx, -cy)\n }\n\n contains(x: number, y: number): boolean {\n // 컨테인즈는 Ellipse로 정의함\n var { cx, cy, rx, ry } = this.model\n\n var normx = (x - cx) / (rx * 2 - 0.5)\n var normy = (y - cy) / (ry * 2 - 0.5)\n\n return normx * normx + normy * normy < 0.25\n }\n\n _post_draw(context: CanvasRenderingContext2D) {\n this.drawText(context)\n }\n\n get nature() {\n return NATURE\n }\n}\n\nComponent.register('gauge-circle', GaugeCircle)\n"]}
@@ -0,0 +1,56 @@
1
+ import { Shape } from '@hatiolab/things-scene';
2
+ declare const GaugeHorizon_base: (new (...args: any[]) => {
3
+ value: number;
4
+ animValue: number;
5
+ animOnValueChange(value: number, animFromBase: boolean, base: number): void;
6
+ }) & typeof Shape;
7
+ export default class GaugeHorizon extends GaugeHorizon_base {
8
+ _draw(context: CanvasRenderingContext2D): void;
9
+ _post_draw(context: CanvasRenderingContext2D): void;
10
+ get nature(): {
11
+ mutable: boolean;
12
+ resizable: boolean;
13
+ rotatable: boolean;
14
+ properties: ({
15
+ type: string;
16
+ label: string;
17
+ name: string;
18
+ property: string;
19
+ observe?: undefined;
20
+ } | {
21
+ type: string;
22
+ label: string;
23
+ name: string;
24
+ observe: (this: HTMLElement, startValue: number) => void;
25
+ property: string;
26
+ } | {
27
+ type: string;
28
+ label: string;
29
+ name: string;
30
+ property: {
31
+ min: number;
32
+ max: number;
33
+ label?: undefined;
34
+ };
35
+ observe?: undefined;
36
+ } | {
37
+ type: string;
38
+ label: string;
39
+ name: string;
40
+ property: {
41
+ label: string;
42
+ min?: undefined;
43
+ max?: undefined;
44
+ };
45
+ observe?: undefined;
46
+ } | {
47
+ type: string;
48
+ label: string;
49
+ name: string;
50
+ property?: undefined;
51
+ observe?: undefined;
52
+ })[];
53
+ help: string;
54
+ };
55
+ }
56
+ export {};
@@ -0,0 +1,145 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { Component, RectPath, Shape, ValueHolder, } from '@hatiolab/things-scene';
5
+ import { PROPERTIES } from './gauge-properties';
6
+ const NATURE = {
7
+ mutable: false,
8
+ resizable: true,
9
+ rotatable: true,
10
+ properties: [
11
+ ...PROPERTIES,
12
+ {
13
+ type: 'color',
14
+ label: 'text-fill-style',
15
+ name: 'textFillStyle',
16
+ property: 'textFillStyle'
17
+ },
18
+ {
19
+ type: 'color',
20
+ label: 'needle-fill-style',
21
+ name: 'needleFillStyle',
22
+ property: 'needleFillStyle'
23
+ },
24
+ {
25
+ type: 'number',
26
+ label: 'needle-size',
27
+ name: 'needleSize',
28
+ property: 'needleSize'
29
+ }
30
+ ],
31
+ help: 'scene/component/gauge-horizon'
32
+ };
33
+ export default class GaugeHorizon extends ValueHolder(RectPath(Shape)) {
34
+ _draw(context) {
35
+ var { startValue, endValue, step, subStep, colorStops, needleFillStyle, stepFillStyle, textFillStyle, needleSize, stepNeedleSize, stepTextSize, showStepText = true, showStartValue = true, showEndValue = true, showStepLine = true, showSubStep = true, width, height, top, left, animFromBase = false } = this.model;
36
+ startValue = Number(startValue);
37
+ this.animOnValueChange(this.value, animFromBase, startValue);
38
+ const totalValue = endValue - startValue; // 게이지의 시작과 끝 값의 크기
39
+ context.translate(left, top); // top과 left의 좌표에 영향을 받지 않기 위해 transalate를 한다음 모든 탑과 레프트의 좌표를 0으로 줌
40
+ //// 메인 막대 그리기 ////
41
+ context.beginPath();
42
+ context.rect(0, 0, width, height);
43
+ this.drawFill(context);
44
+ this.drawStroke(context);
45
+ context.closePath();
46
+ //// 스텝별 색 칠하기 ////
47
+ if (colorStops) {
48
+ let beforeValue = 0;
49
+ colorStops.forEach(function (v, idx, arr) {
50
+ context.beginPath();
51
+ let value = Math.max(Math.min(v.position - startValue, totalValue), 0); // v.position 범위의 최소값은 0, 최대값은 totalValue가 되야함.
52
+ let startStepPosition = (width * beforeValue) / totalValue;
53
+ let endStepPosition;
54
+ // console.log(startStepPosition + (width * value / totalValue));
55
+ if (idx == arr.length - 1 || startStepPosition + (width * value) / totalValue)
56
+ // 배열의 마지막 값이거나 중간 시작값 + 그려지는 값이 width 를 넘을 경우는 무조건 끝까지 채워주도록 한다
57
+ endStepPosition = width - startStepPosition;
58
+ else
59
+ endStepPosition = (width * value) / totalValue;
60
+ if (beforeValue > totalValue || beforeValue > value)
61
+ // 값이 게이지의 최대 값을 넘어가거나 이전 값 보다 현재값이 작으면 다시 그릴 필요 없음
62
+ return false;
63
+ context.rect(startStepPosition, 0, endStepPosition, height);
64
+ context.fillStyle = v.color;
65
+ context.fill();
66
+ beforeValue = value;
67
+ });
68
+ }
69
+ //// 스텝 선 그리기 ////
70
+ context.fillStyle = stepFillStyle;
71
+ if (showStepLine) {
72
+ let count = totalValue / step;
73
+ let stepSize = width * 0.06;
74
+ // Draw StartValue
75
+ context.fillRect(0, height - stepSize, stepNeedleSize, stepSize);
76
+ // Draw StepValue
77
+ for (let num = 1; num < count; num++) {
78
+ let locate = (width / count) * num;
79
+ context.fillRect(locate, height - stepSize, stepNeedleSize, stepSize);
80
+ }
81
+ // Draw EndValue
82
+ context.fillRect(width, height - stepSize, stepNeedleSize, stepSize);
83
+ }
84
+ //// 서브 스탭 그리기 ////
85
+ if (showSubStep) {
86
+ let count = totalValue;
87
+ let subStepSize = width * 0.027;
88
+ // Draw StartValue
89
+ context.fillRect(0, height - subStepSize, stepNeedleSize, subStepSize);
90
+ // Draw StepValue
91
+ for (let num = 1; num <= count; num++) {
92
+ if (num % step == 0 || num % subStep != 0) {
93
+ // 메인 스탭과 서브 스탭은 그리지 않음
94
+ continue;
95
+ }
96
+ let locate = (width / count) * num;
97
+ context.fillRect(locate, height - subStepSize, stepNeedleSize, subStepSize);
98
+ }
99
+ }
100
+ //// 스텝 텍스트 그리기 ////
101
+ let fontSize = (width * stepTextSize) / 150;
102
+ context.fillStyle = textFillStyle;
103
+ context.font = fontSize + 'px arial';
104
+ context.textBaseline = 'middle';
105
+ context.textAlign = 'center';
106
+ if (showStartValue) {
107
+ // Draw StartText
108
+ context.fillText(startValue, 0, height + fontSize * 0.75);
109
+ }
110
+ if (showEndValue) {
111
+ // Draw EndText
112
+ context.fillText(endValue, width, height + fontSize * 0.75);
113
+ }
114
+ if (showStepText) {
115
+ // Draw StepText
116
+ let count = totalValue / step;
117
+ for (let num = 1; num < count; num++) {
118
+ let value = startValue + step * num;
119
+ let locate = (width / count) * num;
120
+ context.fillText(value, locate, height + fontSize * 0.75);
121
+ }
122
+ }
123
+ //// 바늘 그리기 ////
124
+ context.beginPath();
125
+ let drawingValue = this.animValue;
126
+ drawingValue = Math.max(Math.min(drawingValue, endValue), startValue); // 그려지는 값은 startValue보다 작을 수 없고, endValue보다 클 수 없음.
127
+ let position = ((drawingValue - startValue) / totalValue) * width;
128
+ needleSize *= 4;
129
+ context.moveTo(position, height + fontSize * 1.4);
130
+ context.lineTo(position + needleSize / 2, height + needleSize + fontSize * 1.4);
131
+ context.lineTo(position - needleSize / 2, height + needleSize + fontSize * 1.4);
132
+ context.fillStyle = needleFillStyle;
133
+ context.fill();
134
+ context.closePath();
135
+ context.translate(-left, -top);
136
+ }
137
+ _post_draw(context) {
138
+ this.drawText(context);
139
+ }
140
+ get nature() {
141
+ return NATURE;
142
+ }
143
+ }
144
+ Component.register('gauge-horizon', GaugeHorizon);
145
+ //# sourceMappingURL=gauge-horizon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gauge-horizon.js","sourceRoot":"","sources":["../src/gauge-horizon.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport {\n Component,\n RectPath,\n Shape,\n ValueHolder,\n} from '@hatiolab/things-scene';\n\nimport { PROPERTIES } from './gauge-properties';\n\nconst NATURE = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...PROPERTIES,\n {\n type: 'color',\n label: 'text-fill-style',\n name: 'textFillStyle',\n property: 'textFillStyle'\n },\n {\n type: 'color',\n label: 'needle-fill-style',\n name: 'needleFillStyle',\n property: 'needleFillStyle'\n },\n {\n type: 'number',\n label: 'needle-size',\n name: 'needleSize',\n property: 'needleSize'\n }\n ],\n help: 'scene/component/gauge-horizon'\n}\n\nexport default class GaugeHorizon extends ValueHolder(RectPath(Shape)) {\n _draw(context: CanvasRenderingContext2D) {\n var {\n startValue,\n endValue,\n step,\n subStep,\n colorStops,\n needleFillStyle,\n stepFillStyle,\n textFillStyle,\n needleSize,\n stepNeedleSize,\n stepTextSize,\n showStepText = true,\n showStartValue = true,\n showEndValue = true,\n showStepLine = true,\n showSubStep = true,\n width,\n height,\n top,\n left,\n animFromBase = false\n } = this.model\n\n startValue = Number(startValue)\n\n this.animOnValueChange(this.value, animFromBase, startValue)\n\n const totalValue = endValue - startValue // 게이지의 시작과 끝 값의 크기\n\n context.translate(left, top) // top과 left의 좌표에 영향을 받지 않기 위해 transalate를 한다음 모든 탑과 레프트의 좌표를 0으로 줌\n\n //// 메인 막대 그리기 ////\n context.beginPath()\n\n context.rect(0, 0, width, height)\n\n this.drawFill(context)\n this.drawStroke(context)\n context.closePath()\n\n //// 스텝별 색 칠하기 ////\n if (colorStops) {\n let beforeValue = 0\n colorStops.forEach(function (v: {position: number; color: string;}, idx: number, arr: {position: number; color: string;}[]) {\n context.beginPath()\n\n let value = Math.max(Math.min(v.position - startValue, totalValue), 0) // v.position 범위의 최소값은 0, 최대값은 totalValue가 되야함.\n let startStepPosition = (width * beforeValue) / totalValue\n let endStepPosition\n // console.log(startStepPosition + (width * value / totalValue));\n if (idx == arr.length - 1 || startStepPosition + (width * value) / totalValue)\n // 배열의 마지막 값이거나 중간 시작값 + 그려지는 값이 width 를 넘을 경우는 무조건 끝까지 채워주도록 한다\n endStepPosition = width - startStepPosition\n else endStepPosition = (width * value) / totalValue\n\n if (beforeValue > totalValue || beforeValue > value)\n // 값이 게이지의 최대 값을 넘어가거나 이전 값 보다 현재값이 작으면 다시 그릴 필요 없음\n return false\n\n context.rect(startStepPosition, 0, endStepPosition, height)\n\n context.fillStyle = v.color\n context.fill()\n\n beforeValue = value\n })\n }\n\n //// 스텝 선 그리기 ////\n context.fillStyle = stepFillStyle\n if (showStepLine) {\n let count = totalValue / step\n let stepSize = width * 0.06\n\n // Draw StartValue\n context.fillRect(0, height - stepSize, stepNeedleSize, stepSize)\n // Draw StepValue\n for (let num = 1; num < count; num++) {\n let locate = (width / count) * num\n\n context.fillRect(locate, height - stepSize, stepNeedleSize, stepSize)\n }\n // Draw EndValue\n context.fillRect(width, height - stepSize, stepNeedleSize, stepSize)\n }\n\n //// 서브 스탭 그리기 ////\n if (showSubStep) {\n let count = totalValue\n let subStepSize = width * 0.027\n // Draw StartValue\n context.fillRect(0, height - subStepSize, stepNeedleSize, subStepSize)\n\n // Draw StepValue\n for (let num = 1; num <= count; num++) {\n if (num % step == 0 || num % subStep != 0) {\n // 메인 스탭과 서브 스탭은 그리지 않음\n continue\n }\n let locate = (width / count) * num\n context.fillRect(locate, height - subStepSize, stepNeedleSize, subStepSize)\n }\n }\n\n //// 스텝 텍스트 그리기 ////\n let fontSize = (width * stepTextSize) / 150\n context.fillStyle = textFillStyle\n context.font = fontSize + 'px arial'\n context.textBaseline = 'middle'\n context.textAlign = 'center'\n if (showStartValue) {\n // Draw StartText\n context.fillText(startValue, 0, height + fontSize * 0.75)\n }\n\n if (showEndValue) {\n // Draw EndText\n context.fillText(endValue, width, height + fontSize * 0.75)\n }\n\n if (showStepText) {\n // Draw StepText\n let count = totalValue / step\n\n for (let num = 1; num < count; num++) {\n let value = startValue + step * num\n let locate = (width / count) * num\n\n context.fillText(value, locate, height + fontSize * 0.75)\n }\n }\n\n //// 바늘 그리기 ////\n context.beginPath()\n let drawingValue = this.animValue\n drawingValue = Math.max(Math.min(drawingValue, endValue), startValue) // 그려지는 값은 startValue보다 작을 수 없고, endValue보다 클 수 없음.\n let position = ((drawingValue - startValue) / totalValue) * width\n\n needleSize *= 4\n context.moveTo(position, height + fontSize * 1.4)\n context.lineTo(position + needleSize / 2, height + needleSize + fontSize * 1.4)\n context.lineTo(position - needleSize / 2, height + needleSize + fontSize * 1.4)\n\n context.fillStyle = needleFillStyle\n context.fill()\n context.closePath()\n\n context.translate(-left, -top)\n }\n\n _post_draw(context: CanvasRenderingContext2D) {\n this.drawText(context)\n }\n\n get nature() {\n return NATURE\n }\n}\n\nComponent.register('gauge-horizon', GaugeHorizon)\n"]}
@@ -0,0 +1,39 @@
1
+ export declare const PROPERTIES: ({
2
+ type: string;
3
+ label: string;
4
+ name: string;
5
+ property: string;
6
+ observe?: undefined;
7
+ } | {
8
+ type: string;
9
+ label: string;
10
+ name: string;
11
+ observe: (this: HTMLElement, startValue: number) => void;
12
+ property: string;
13
+ } | {
14
+ type: string;
15
+ label: string;
16
+ name: string;
17
+ property: {
18
+ min: number;
19
+ max: number;
20
+ label?: undefined;
21
+ };
22
+ observe?: undefined;
23
+ } | {
24
+ type: string;
25
+ label: string;
26
+ name: string;
27
+ property: {
28
+ label: string;
29
+ min?: undefined;
30
+ max?: undefined;
31
+ };
32
+ observe?: undefined;
33
+ } | {
34
+ type: string;
35
+ label: string;
36
+ name: string;
37
+ property?: undefined;
38
+ observe?: undefined;
39
+ })[];