@fmsim/machine 2.0.0-beta.99 → 2.0.0
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.
- package/dist/carrier-manager.js +9 -1
- package/dist/carrier-manager.js.map +1 -1
- package/dist/carrier.js +69 -52
- package/dist/carrier.js.map +1 -1
- package/dist/crane.js +15 -6
- package/dist/crane.js.map +1 -1
- package/dist/factories/agv-3d.js +9 -27
- package/dist/factories/agv-3d.js.map +1 -1
- package/dist/factories/conveyor-3d.js +11 -19
- package/dist/factories/conveyor-3d.js.map +1 -1
- package/dist/factories/crane-3d.js +8 -17
- package/dist/factories/crane-3d.js.map +1 -1
- package/dist/factories/crane-rail-3d.js +8 -12
- package/dist/factories/crane-rail-3d.js.map +1 -1
- package/dist/factories/machine-3d.js +100 -63
- package/dist/factories/machine-3d.js.map +1 -1
- package/dist/factories/oht-3d.js +9 -27
- package/dist/factories/oht-3d.js.map +1 -1
- package/dist/factories/shuttle-3d.js +11 -27
- package/dist/factories/shuttle-3d.js.map +1 -1
- package/dist/features/capacity-gauge-mixin.js +520 -0
- package/dist/features/capacity-gauge-mixin.js.map +1 -0
- package/dist/features/mcs-status-default.js +13 -0
- package/dist/features/mcs-status-default.js.map +1 -1
- package/dist/features/parent-object-mixin.js +5 -1
- package/dist/features/parent-object-mixin.js.map +1 -1
- package/dist/mcs-machine.js +4 -23
- package/dist/mcs-machine.js.map +1 -1
- package/dist/mcs-unit.js +2 -5
- package/dist/mcs-unit.js.map +1 -1
- package/dist/mcs-vehicle.js +3 -1
- package/dist/mcs-vehicle.js.map +1 -1
- package/dist/scene/root-container-override.js +5 -2
- package/dist/scene/root-container-override.js.map +1 -1
- package/dist/stocker-capacity-bar.js +11 -372
- package/dist/stocker-capacity-bar.js.map +1 -1
- package/dist/stocker.js +29 -1
- package/dist/stocker.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/crane-position.js +23 -14
- package/dist/utils/crane-position.js.map +1 -1
- package/dist/utils/stocker-gauge.js +48 -10
- package/dist/utils/stocker-gauge.js.map +1 -1
- package/dist/zone-capacity-bar.js +13 -213
- package/dist/zone-capacity-bar.js.map +1 -1
- package/package.json +4 -4
- package/src/carrier-manager.ts +9 -1
- package/src/carrier.ts +73 -52
- package/src/crane.ts +14 -5
- package/src/factories/agv-3d.ts +10 -26
- package/src/factories/conveyor-3d.ts +12 -19
- package/src/factories/crane-3d.ts +9 -17
- package/src/factories/crane-rail-3d.ts +9 -13
- package/src/factories/machine-3d.ts +125 -66
- package/src/factories/oht-3d.ts +10 -26
- package/src/factories/shuttle-3d.ts +12 -26
- package/src/features/capacity-gauge-mixin.ts +642 -0
- package/src/features/mcs-status-default.ts +13 -0
- package/src/features/parent-object-mixin.ts +5 -1
- package/src/mcs-machine.ts +4 -23
- package/src/mcs-unit.ts +2 -5
- package/src/mcs-vehicle.ts +3 -1
- package/src/scene/root-container-override.ts +5 -2
- package/src/stocker-capacity-bar.ts +15 -476
- package/src/stocker.ts +29 -1
- package/src/utils/crane-position.ts +46 -14
- package/src/utils/stocker-gauge.ts +63 -10
- package/src/zone-capacity-bar.ts +17 -282
- package/translations/en.json +4 -1
- package/translations/ja.json +4 -1
- package/translations/ko.json +4 -1
- package/translations/ms.json +4 -1
- package/translations/zh.json +4 -1
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* }
|
|
11
11
|
*
|
|
12
12
|
* current 를 limit 범위 안의 0~1 비율로 환산한 뒤 host(부모) footprint 에 매핑한다.
|
|
13
|
-
*
|
|
13
|
+
* z → 포크 높이(forkZ 0~100). x/y 의 축 배정과 원점은 host 좌표계 설정(CoordMapping)을
|
|
14
|
+
* 따르고, 미설정 시 x → host 긴쪽, y → 짧은쪽, 원점 = 좌상단.
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
import { parseIfJsonString } from './data-value'
|
|
@@ -39,6 +40,26 @@ export function axisRatio(value: unknown, lim?: AxisLimit): number {
|
|
|
39
40
|
return Math.max(0, Math.min(1, (v - min) / (max - min)))
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* host(보통 STOCKER) 의 **내부 좌표계** 설정 — host state 에서 읽는다.
|
|
45
|
+
*
|
|
46
|
+
* 외부 시스템이 보내는 좌표의 X/Y 를 host footprint 의 어느 축·어느 방향에 대응시킬지
|
|
47
|
+
* 정한다. 크레인 전용이 아니라 host 자신의 좌표 규약이므로, 같은 좌표계를 쓰는 다른
|
|
48
|
+
* 자식(Shelf 등)도 동일하게 참조할 수 있다. 모두 미설정이면 종전 동작(긴쪽=X,
|
|
49
|
+
* 원점=left/top)과 같다.
|
|
50
|
+
*
|
|
51
|
+
* 주의: **로컬 프레임 기준**이다. host 회전(rotation)은 렌더 단계에서 적용되므로,
|
|
52
|
+
* 이 설정은 회전 전 모델 좌표계로 이해해야 한다.
|
|
53
|
+
*/
|
|
54
|
+
export type CoordMapping = {
|
|
55
|
+
/** 내부 X 가 달리는 축. 'auto'(기본) = 긴 변. */
|
|
56
|
+
axisX?: 'auto' | 'width' | 'height'
|
|
57
|
+
/** X=0 을 반대쪽 끝으로. */
|
|
58
|
+
invertX?: boolean
|
|
59
|
+
/** Y=0 을 반대쪽 끝으로. */
|
|
60
|
+
invertY?: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
42
63
|
/**
|
|
43
64
|
* host(부모) footprint 안에서 0~1 비율 (rx,ry) → 크레인 top-left 로컬 좌표.
|
|
44
65
|
*
|
|
@@ -47,7 +68,8 @@ export function axisRatio(value: unknown, lim?: AxisLimit): number {
|
|
|
47
68
|
* craneLen/2 만큼 inset 된 중심선 위를 움직임). 크레인이 host 보다 크면 span 0
|
|
48
69
|
* 으로 떨어져 host 모서리에 정렬.
|
|
49
70
|
*
|
|
50
|
-
*
|
|
71
|
+
* 축 배정과 원점은 opts(CoordMapping = host 의 내부 좌표계 설정)로 정한다. 기본(미설정)은
|
|
72
|
+
* x(rx) → host 의 긴쪽, y(ry) → 짧은쪽, 원점 = left/top.
|
|
51
73
|
*/
|
|
52
74
|
export function mapCraneLocalPosition(
|
|
53
75
|
hostW: number,
|
|
@@ -55,24 +77,34 @@ export function mapCraneLocalPosition(
|
|
|
55
77
|
craneW: number,
|
|
56
78
|
craneH: number,
|
|
57
79
|
rx: number,
|
|
58
|
-
ry: number
|
|
80
|
+
ry: number,
|
|
81
|
+
opts: CoordMapping = {}
|
|
59
82
|
): { left: number; top: number } {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
// 내부 X 가 달리는 축 배정: 명시 설정 우선, 'auto'/미설정은 긴 변(종전 폴백).
|
|
84
|
+
// 정사각형에 가까운 host 는 auto 가 리사이즈로 뒤집힐 수 있어 명시 지정을 권한다.
|
|
85
|
+
const xIsWidth = opts.axisX === 'width' ? true : opts.axisX === 'height' ? false : hostW >= hostH
|
|
86
|
+
|
|
87
|
+
// 반전은 *비율 단계*에서 흡수 — pos = (1-r)*span 이 위치 뒤집기와 동일하고 더 단순하다.
|
|
88
|
+
const fx = opts.invertX ? 1 - rx : rx
|
|
89
|
+
const fy = opts.invertY ? 1 - ry : ry
|
|
90
|
+
|
|
91
|
+
// 데이터 X/Y 축 기준으로 길이를 잡는다. axisX 를 명시하면 X 가 짧은 변일 수도 있으므로
|
|
92
|
+
// 길이(long/short)가 아니라 축 이름으로 부른다.
|
|
93
|
+
const xLen = xIsWidth ? hostW : hostH
|
|
94
|
+
const yLen = xIsWidth ? hostH : hostW
|
|
95
|
+
const craneXSize = xIsWidth ? craneW : craneH
|
|
96
|
+
const craneYSize = xIsWidth ? craneH : craneW
|
|
65
97
|
|
|
66
98
|
// 크레인 크기를 뺀 inset 가용 span. top-left = ratio * span 이므로 크레인
|
|
67
99
|
// 전체가 host [0, hostLen] 안에 들어온다.
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const
|
|
100
|
+
const xSpan = Math.max(0, xLen - craneXSize)
|
|
101
|
+
const ySpan = Math.max(0, yLen - craneYSize)
|
|
102
|
+
const xPos = fx * xSpan
|
|
103
|
+
const yPos = fy * ySpan
|
|
72
104
|
|
|
73
105
|
return {
|
|
74
|
-
left:
|
|
75
|
-
top:
|
|
106
|
+
left: xIsWidth ? xPos : yPos,
|
|
107
|
+
top: xIsWidth ? yPos : xPos
|
|
76
108
|
}
|
|
77
109
|
}
|
|
78
110
|
|
|
@@ -11,9 +11,13 @@
|
|
|
11
11
|
* - abnormal : CARRIER_NORMAL / CARRIER_ABNORMAL
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import { Legend } from '../features/mcs-status-default'
|
|
15
|
+
|
|
14
16
|
export type StockerGaugeMode = 'capacity' | 'carrier' | 'abnormal'
|
|
15
17
|
|
|
16
18
|
export interface GaugeSegment {
|
|
19
|
+
/** 안정적 식별 토큰 (대문자, 클릭 이벤트 payload·데이터 필드 관례와 일치). */
|
|
20
|
+
key: 'FULL' | 'EMPTY' | 'EMPTYEMPTY' | 'NORMAL' | 'ABNORMAL'
|
|
17
21
|
/** 세그먼트 라벨(2D per-segment 표시용, '\n' 은 줄바꿈). */
|
|
18
22
|
label: string
|
|
19
23
|
/** 카운트 원본값. */
|
|
@@ -24,13 +28,33 @@ export interface GaugeSegment {
|
|
|
24
28
|
color: string
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
/** carrier 세그먼트 색상 (2D/3D 공통). */
|
|
31
|
+
/** carrier 세그먼트 색상 (2D/3D 공통). LEGEND_CARRIER 기본값과 동일 — 테마 미지정 시 폴백. */
|
|
28
32
|
export const CARRIER_COLORS = {
|
|
29
33
|
full: '#4AA7FE',
|
|
30
34
|
empty: '#8BDA5B',
|
|
31
35
|
emptyEmpty: '#019D59'
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
export interface CarrierColors {
|
|
39
|
+
full: string
|
|
40
|
+
empty: string
|
|
41
|
+
emptyEmpty: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* carrier legend(테마)에서 full/empty/emptyEmpty 색상 추출.
|
|
46
|
+
* carrier 컴포넌트의 색 취득 로직(statusColor = legend[status] || legend.default)과 동일하게,
|
|
47
|
+
* status 키(FULL/EMPTY/EMPTYEMPTY)로 직접 조회한다. 키/default 모두 없으면 CARRIER_COLORS 로 폴백.
|
|
48
|
+
*/
|
|
49
|
+
export function carrierColorsFromLegend(legend?: Legend): CarrierColors {
|
|
50
|
+
const pick = (key: string, fallback: string) => (legend && (legend[key] || legend.default)) || fallback
|
|
51
|
+
return {
|
|
52
|
+
full: pick('FULL', CARRIER_COLORS.full),
|
|
53
|
+
empty: pick('EMPTY', CARRIER_COLORS.empty),
|
|
54
|
+
emptyEmpty: pick('EMPTYEMPTY', CARRIER_COLORS.emptyEmpty)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
34
58
|
/** abnormal 세그먼트 색상 (2D/3D 공통). */
|
|
35
59
|
export const ABNORMAL_COLORS = {
|
|
36
60
|
normal: '#8BDA5B',
|
|
@@ -42,17 +66,25 @@ function num(v: unknown): number {
|
|
|
42
66
|
return Number.isFinite(n) && n > 0 ? n : 0
|
|
43
67
|
}
|
|
44
68
|
|
|
45
|
-
/**
|
|
46
|
-
|
|
69
|
+
/**
|
|
70
|
+
* 캐리어 상태 세그먼트 (Full / Empty / EmptyEmpty). total 0 이면 모든 ratio 0.
|
|
71
|
+
* colors 미지정 시 CARRIER_COLORS(기본). 테마 색은 carrierColorsFromLegend 로 만들어 전달.
|
|
72
|
+
*/
|
|
73
|
+
export function carrierSegments(
|
|
74
|
+
full: unknown,
|
|
75
|
+
empty: unknown,
|
|
76
|
+
emptyEmpty: unknown,
|
|
77
|
+
colors: CarrierColors = CARRIER_COLORS
|
|
78
|
+
): GaugeSegment[] {
|
|
47
79
|
const f = num(full)
|
|
48
80
|
const e = num(empty)
|
|
49
81
|
const ee = num(emptyEmpty)
|
|
50
82
|
const total = f + e + ee
|
|
51
83
|
const r = (c: number) => (total > 0 ? c / total : 0)
|
|
52
84
|
return [
|
|
53
|
-
{ label: 'Full', count: f, ratio: r(f), color:
|
|
54
|
-
{ label: 'Empty', count: e, ratio: r(e), color:
|
|
55
|
-
{ label: 'Empty\nEmpty', count: ee, ratio: r(ee), color:
|
|
85
|
+
{ key: 'FULL', label: 'Full', count: f, ratio: r(f), color: colors.full },
|
|
86
|
+
{ key: 'EMPTY', label: 'Empty', count: e, ratio: r(e), color: colors.empty },
|
|
87
|
+
{ key: 'EMPTYEMPTY', label: 'Empty\nEmpty', count: ee, ratio: r(ee), color: colors.emptyEmpty }
|
|
56
88
|
]
|
|
57
89
|
}
|
|
58
90
|
|
|
@@ -63,15 +95,36 @@ export function abnormalSegments(normal: unknown, abnormal: unknown): GaugeSegme
|
|
|
63
95
|
const total = n + a
|
|
64
96
|
const r = (c: number) => (total > 0 ? c / total : 0)
|
|
65
97
|
return [
|
|
66
|
-
{ label: 'Normal', count: n, ratio: r(n), color: ABNORMAL_COLORS.normal },
|
|
67
|
-
{ label: 'Abnormal', count: a, ratio: r(a), color: ABNORMAL_COLORS.abnormal }
|
|
98
|
+
{ key: 'NORMAL', label: 'Normal', count: n, ratio: r(n), color: ABNORMAL_COLORS.normal },
|
|
99
|
+
{ key: 'ABNORMAL', label: 'Abnormal', count: a, ratio: r(a), color: ABNORMAL_COLORS.abnormal }
|
|
68
100
|
]
|
|
69
101
|
}
|
|
70
102
|
|
|
103
|
+
/**
|
|
104
|
+
* 누적 비율 위치(pos, 0..span 범위)가 속한 세그먼트를 반환한다. ratio 0 세그먼트는
|
|
105
|
+
* 화면에 없으므로 건너뛴다. 경계(pos == span)·초과 클릭은 마지막 비영 세그먼트로 귀속하고,
|
|
106
|
+
* 데이터가 전혀 없으면(모든 ratio 0) null.
|
|
107
|
+
*
|
|
108
|
+
* renderSegmentGauge 의 배치와 동일 규칙(누적 채움)이며, 2D 렌더와 클릭 판정이 이 함수를
|
|
109
|
+
* 공유해 drift 를 막는다. 방향(landscape 왼→오 / portrait 아래→위)은 호출부가 pos 로 흡수한다.
|
|
110
|
+
*/
|
|
111
|
+
export function pickSegmentAt(segments: GaugeSegment[], pos: number, span: number): GaugeSegment | null {
|
|
112
|
+
let acc = 0
|
|
113
|
+
let lastNonZero: GaugeSegment | null = null
|
|
114
|
+
for (const seg of segments) {
|
|
115
|
+
const segLen = span * seg.ratio
|
|
116
|
+
if (segLen <= 0) continue
|
|
117
|
+
lastNonZero = seg
|
|
118
|
+
if (pos < acc + segLen) return seg
|
|
119
|
+
acc += segLen
|
|
120
|
+
}
|
|
121
|
+
return lastNonZero
|
|
122
|
+
}
|
|
123
|
+
|
|
71
124
|
/** 캐리어 세그먼트 — canonical raw data(CARRIER_*) 에서 직접. 3D 처럼 raw data 소스용. */
|
|
72
|
-
export function carrierSegmentsFromData(data: any): GaugeSegment[] {
|
|
125
|
+
export function carrierSegmentsFromData(data: any, colors?: CarrierColors): GaugeSegment[] {
|
|
73
126
|
const d = data && typeof data === 'object' ? data : {}
|
|
74
|
-
return carrierSegments(d.CARRIER_FULL, d.CARRIER_EMPTY, d.CARRIER_EMPTY_EMPTY)
|
|
127
|
+
return carrierSegments(d.CARRIER_FULL, d.CARRIER_EMPTY, d.CARRIER_EMPTY_EMPTY, colors)
|
|
75
128
|
}
|
|
76
129
|
|
|
77
130
|
/** 비정상 세그먼트 — canonical raw data(CARRIER_*) 에서 직접. */
|
package/src/zone-capacity-bar.ts
CHANGED
|
@@ -1,301 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { LEGEND_CAPACITY } from './features/mcs-status-default'
|
|
4
|
-
import { safeRound } from './utils/safe-round'
|
|
5
|
-
import { getValueOnRanges } from './utils/get-value-on-ranges'
|
|
1
|
+
import { ComponentNature, sceneComponent } from '@hatiolab/things-scene'
|
|
2
|
+
import { LEGEND_CAPACITY, Legend } from './features/mcs-status-default'
|
|
6
3
|
import { MCSZoneMixin, MCSZoneMixinProperties } from './features/mcs-zone-mixin'
|
|
7
4
|
import { ParentObjectMixinProperties } from './features/parent-object-mixin'
|
|
5
|
+
import { CapacityGaugeMixin, CapacityGaugeMixinProperties } from './features/capacity-gauge-mixin'
|
|
8
6
|
import MCSUnit from './mcs-unit'
|
|
9
7
|
|
|
8
|
+
/**
|
|
9
|
+
* 존(zone) 게이지.
|
|
10
|
+
*
|
|
11
|
+
* mode 에 따라 capacity / carrier / abnormal 3가지 게이지를 표현한다 — 그리는 규칙은
|
|
12
|
+
* StockerCapacityBar 와 동일하며 CapacityGaugeMixin 에서 공유한다(단일 소스).
|
|
13
|
+
* 스토커 게이지와 달리 존 게이지는 자체 id 로 데이터를 받는 Unit(identifiable) 이며,
|
|
14
|
+
* legend 폴백만 zone 전역 테마(zoneCapacityLegendTheme)로 다르다.
|
|
15
|
+
*
|
|
16
|
+
* mode 소스: root.stockerGaugeMode — 스토커 게이지와 같은 런타임 스위치로 함께 전환된다.
|
|
17
|
+
*/
|
|
18
|
+
|
|
10
19
|
const NATURE: ComponentNature = {
|
|
11
20
|
mutable: false,
|
|
12
21
|
resizable: true,
|
|
13
22
|
rotatable: true,
|
|
14
|
-
properties: [
|
|
15
|
-
...MCSZoneMixinProperties,
|
|
16
|
-
...ParentObjectMixinProperties,
|
|
17
|
-
{
|
|
18
|
-
type: 'select',
|
|
19
|
-
label: 'legend-name',
|
|
20
|
-
name: 'legendName',
|
|
21
|
-
property: {
|
|
22
|
-
options: themesColorRange
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
type: 'number',
|
|
27
|
-
name: 'currentUsage',
|
|
28
|
-
label: 'current-usage'
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
type: 'number',
|
|
32
|
-
name: 'highWatermark',
|
|
33
|
-
label: 'high-watermark'
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: 'number',
|
|
37
|
-
name: 'lowWatermark',
|
|
38
|
-
label: 'low-watermark'
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
type: 'number',
|
|
42
|
-
name: 'maxCapacity',
|
|
43
|
-
label: 'max-capacity'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
type: 'boolean',
|
|
47
|
-
name: 'fullup',
|
|
48
|
-
label: 'fullup'
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
type: 'number',
|
|
52
|
-
label: 'round',
|
|
53
|
-
name: 'round',
|
|
54
|
-
property: {
|
|
55
|
-
min: 0
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
type: 'hidden',
|
|
60
|
-
name: 'usage',
|
|
61
|
-
label: 'usage'
|
|
62
|
-
}
|
|
63
|
-
],
|
|
23
|
+
properties: [...MCSZoneMixinProperties, ...ParentObjectMixinProperties, ...CapacityGaugeMixinProperties],
|
|
64
24
|
'value-property': 'usage'
|
|
65
25
|
}
|
|
66
26
|
|
|
67
|
-
var controlHandler = {
|
|
68
|
-
ondragmove: function (point: POSITION, index: number, component: Component) {
|
|
69
|
-
var { left, top, width, height } = component.model
|
|
70
|
-
|
|
71
|
-
var transcoorded = component.transcoordP2S(point.x, point.y)
|
|
72
|
-
var round = ((transcoorded.x - left) / (width / 2)) * 100
|
|
73
|
-
|
|
74
|
-
round = safeRound(round, width, height)
|
|
75
|
-
|
|
76
|
-
component.set({
|
|
77
|
-
round
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
27
|
@sceneComponent('ZoneCapacityBar')
|
|
83
|
-
export default class ZoneCapacityBar extends MCSZoneMixin(MCSUnit) {
|
|
28
|
+
export default class ZoneCapacityBar extends CapacityGaugeMixin(MCSZoneMixin(MCSUnit)) {
|
|
84
29
|
static get nature() {
|
|
85
30
|
return NATURE
|
|
86
31
|
}
|
|
87
32
|
|
|
88
|
-
|
|
89
|
-
var { left, top, width, round, height } = this.state
|
|
90
|
-
round = round == undefined ? 0 : safeRound(round, width, height)
|
|
91
|
-
|
|
92
|
-
return [
|
|
93
|
-
{
|
|
94
|
-
x: left + (width / 2) * (round / 100),
|
|
95
|
-
y: top,
|
|
96
|
-
handler: controlHandler
|
|
97
|
-
}
|
|
98
|
-
]
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
getLegendFallback() {
|
|
33
|
+
getLegendFallback(): Legend {
|
|
102
34
|
return (this.root as any).zoneCapacityLegendTheme || LEGEND_CAPACITY
|
|
103
35
|
}
|
|
104
|
-
|
|
105
|
-
get statusColor() {
|
|
106
|
-
const { fullup } = this.state
|
|
107
|
-
return fullup ? 'red' : getValueOnRanges(this.usage, this.legend)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
get text() {
|
|
111
|
-
return this.usage + '%'
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
render(context: CanvasRenderingContext2D) {
|
|
115
|
-
const { left, top, width, height } = this.bounds
|
|
116
|
-
|
|
117
|
-
if (width >= height) {
|
|
118
|
-
this.renderLandscape(context)
|
|
119
|
-
} else {
|
|
120
|
-
this.renderPortrait(context)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
renderLandscape(context: CanvasRenderingContext2D) {
|
|
125
|
-
const { left, top, width, height } = this.bounds
|
|
126
|
-
const { highWatermark, lowWatermark, lineWidth, strokeStyle, round, fillStyle = 'white' } = this.state
|
|
127
|
-
|
|
128
|
-
context.save()
|
|
129
|
-
context.translate(left, top)
|
|
130
|
-
|
|
131
|
-
// gauge background
|
|
132
|
-
context.beginPath()
|
|
133
|
-
|
|
134
|
-
context.fillStyle = fillStyle
|
|
135
|
-
context.roundRect(0, 0, width, height, round)
|
|
136
|
-
|
|
137
|
-
context.fill()
|
|
138
|
-
context.stroke()
|
|
139
|
-
|
|
140
|
-
context.clip()
|
|
141
|
-
|
|
142
|
-
// gauge foreground
|
|
143
|
-
context.beginPath()
|
|
144
|
-
|
|
145
|
-
context.fillStyle = this.statusColor!
|
|
146
|
-
|
|
147
|
-
context.rect(0, 0, (width / 100) * this.usage, height)
|
|
148
|
-
context.fill()
|
|
149
|
-
|
|
150
|
-
// high-watermark level
|
|
151
|
-
|
|
152
|
-
if (highWatermark && highWatermark > 0 && highWatermark < 100) {
|
|
153
|
-
context.beginPath()
|
|
154
|
-
|
|
155
|
-
context.strokeStyle = 'black'
|
|
156
|
-
context.lineWidth = 1
|
|
157
|
-
context.setLineDash([3])
|
|
158
|
-
|
|
159
|
-
const x = (width / 100) * highWatermark
|
|
160
|
-
context.moveTo(x, 0)
|
|
161
|
-
context.lineTo(x, height)
|
|
162
|
-
|
|
163
|
-
context.stroke()
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// low-watermark level
|
|
167
|
-
|
|
168
|
-
if (lowWatermark && lowWatermark > 0 && lowWatermark < 100) {
|
|
169
|
-
context.beginPath()
|
|
170
|
-
|
|
171
|
-
context.strokeStyle = 'black'
|
|
172
|
-
context.lineWidth = 1
|
|
173
|
-
context.setLineDash([3])
|
|
174
|
-
|
|
175
|
-
const x = (width / 100) * lowWatermark
|
|
176
|
-
context.moveTo(x, 0)
|
|
177
|
-
context.lineTo(x, height)
|
|
178
|
-
|
|
179
|
-
context.stroke()
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// gauge outline
|
|
183
|
-
context.beginPath()
|
|
184
|
-
|
|
185
|
-
context.setLineDash([])
|
|
186
|
-
context.strokeStyle = strokeStyle
|
|
187
|
-
context.lineWidth = lineWidth
|
|
188
|
-
context.roundRect(0, 0, width, height, round)
|
|
189
|
-
context.stroke()
|
|
190
|
-
|
|
191
|
-
context.beginPath()
|
|
192
|
-
|
|
193
|
-
context.translate(-left, -top)
|
|
194
|
-
context.restore()
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
renderPortrait(context: CanvasRenderingContext2D) {
|
|
198
|
-
const { left, top, width, height } = this.bounds
|
|
199
|
-
const { highWatermark, lowWatermark, lineWidth, strokeStyle, round, fillStyle = 'white' } = this.state
|
|
200
|
-
|
|
201
|
-
context.save()
|
|
202
|
-
context.translate(left, top)
|
|
203
|
-
|
|
204
|
-
// gauge background
|
|
205
|
-
context.beginPath()
|
|
206
|
-
|
|
207
|
-
context.fillStyle = fillStyle
|
|
208
|
-
context.roundRect(0, 0, width, height, round)
|
|
209
|
-
|
|
210
|
-
context.fill()
|
|
211
|
-
|
|
212
|
-
context.clip()
|
|
213
|
-
|
|
214
|
-
// gauge foreground
|
|
215
|
-
context.beginPath()
|
|
216
|
-
|
|
217
|
-
context.fillStyle = this.statusColor!
|
|
218
|
-
|
|
219
|
-
context.rect(0, height - (height / 100) * this.usage, width, (height / 100) * this.usage)
|
|
220
|
-
context.fill()
|
|
221
|
-
|
|
222
|
-
// high-watermark level
|
|
223
|
-
|
|
224
|
-
if (highWatermark && highWatermark > 0 && highWatermark < 100) {
|
|
225
|
-
context.beginPath()
|
|
226
|
-
|
|
227
|
-
context.strokeStyle = 'black'
|
|
228
|
-
context.lineWidth = 1
|
|
229
|
-
context.setLineDash([3])
|
|
230
|
-
|
|
231
|
-
const y = height - (height / 100) * highWatermark
|
|
232
|
-
context.moveTo(0, y)
|
|
233
|
-
context.lineTo(width, y)
|
|
234
|
-
|
|
235
|
-
context.stroke()
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// low-watermark level
|
|
239
|
-
|
|
240
|
-
if (lowWatermark && lowWatermark > 0 && lowWatermark < 100) {
|
|
241
|
-
context.beginPath()
|
|
242
|
-
|
|
243
|
-
context.strokeStyle = 'black'
|
|
244
|
-
context.lineWidth = 1
|
|
245
|
-
context.setLineDash([3])
|
|
246
|
-
|
|
247
|
-
const y = height - (height / 100) * lowWatermark
|
|
248
|
-
context.moveTo(0, y)
|
|
249
|
-
context.lineTo(width, y)
|
|
250
|
-
|
|
251
|
-
context.stroke()
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// gauge outline
|
|
255
|
-
context.beginPath()
|
|
256
|
-
|
|
257
|
-
context.setLineDash([])
|
|
258
|
-
context.strokeStyle = strokeStyle
|
|
259
|
-
context.lineWidth = lineWidth
|
|
260
|
-
context.roundRect(0, 0, width, height, round)
|
|
261
|
-
context.stroke()
|
|
262
|
-
|
|
263
|
-
context.beginPath()
|
|
264
|
-
|
|
265
|
-
context.translate(-left, -top)
|
|
266
|
-
context.restore()
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
get usage() {
|
|
270
|
-
const { currentUsage = 0, maxCapacity = 100 } = this.state
|
|
271
|
-
return Math.round((currentUsage / maxCapacity) * 100)
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
set usage(usage: number) {
|
|
275
|
-
// intentionally have done nothing
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
onchangeData(after: Record<string, any>, before: Record<string, any>): void {
|
|
279
|
-
const {
|
|
280
|
-
CURRENTCAPACITY = 0,
|
|
281
|
-
MAXCAPACITY = 100,
|
|
282
|
-
HIGHWATERMARK = 100,
|
|
283
|
-
LOWWATERMARK = 0,
|
|
284
|
-
FULLUP = 'F'
|
|
285
|
-
} = this.data && typeof this.data == 'object' ? this.data : {}
|
|
286
|
-
|
|
287
|
-
const currentUsage = Number(CURRENTCAPACITY) || 0
|
|
288
|
-
const maxCapacity = Number(MAXCAPACITY) || 100
|
|
289
|
-
const highWatermark = Number(HIGHWATERMARK) || 100
|
|
290
|
-
const lowWatermark = Number(LOWWATERMARK) || 0
|
|
291
|
-
|
|
292
|
-
this.setState({
|
|
293
|
-
currentUsage,
|
|
294
|
-
maxCapacity,
|
|
295
|
-
highWatermark,
|
|
296
|
-
lowWatermark,
|
|
297
|
-
fullup: FULLUP == 'T',
|
|
298
|
-
usage: Math.round((currentUsage / maxCapacity) * 100)
|
|
299
|
-
})
|
|
300
|
-
}
|
|
301
36
|
}
|
package/translations/en.json
CHANGED
|
@@ -71,5 +71,8 @@
|
|
|
71
71
|
"label.light-preset": "light preset",
|
|
72
72
|
"label.dark": "dark",
|
|
73
73
|
"label.medium": "medium",
|
|
74
|
-
"label.bright": "bright"
|
|
74
|
+
"label.bright": "bright",
|
|
75
|
+
"label.coord-axis-x": "internal x axis",
|
|
76
|
+
"label.coord-invert-x": "invert x origin",
|
|
77
|
+
"label.coord-invert-y": "invert y origin"
|
|
75
78
|
}
|
package/translations/ja.json
CHANGED
package/translations/ko.json
CHANGED
package/translations/ms.json
CHANGED
|
@@ -73,5 +73,8 @@
|
|
|
73
73
|
"label.light-preset": "pratetapan cahaya",
|
|
74
74
|
"label.dark": "gelap",
|
|
75
75
|
"label.medium": "sederhana",
|
|
76
|
-
"label.bright": "cerah"
|
|
76
|
+
"label.bright": "cerah",
|
|
77
|
+
"label.coord-axis-x": "internal x axis",
|
|
78
|
+
"label.coord-invert-x": "invert x origin",
|
|
79
|
+
"label.coord-invert-y": "invert y origin"
|
|
77
80
|
}
|
package/translations/zh.json
CHANGED