@oicl/openbridge-webcomponents 2.0.0-next.56 → 2.0.0-next.58
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/bundle/openbridge-webcomponents.bundle.js +987 -362
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +576 -10
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +10 -0
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
- package/dist/building-blocks/instrument-radial/instrument-radial.js +86 -21
- package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.css.js +12 -0
- package/dist/navigation-instruments/compass-sector/compass-sector.css.js.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.d.ts +23 -0
- package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.js +47 -0
- package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +99 -0
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -0
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts +42 -7
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js +178 -31
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js.map +1 -1
- package/dist/navigation-instruments/pitch/pitch.d.ts +37 -0
- package/dist/navigation-instruments/pitch/pitch.d.ts.map +1 -1
- package/dist/navigation-instruments/pitch/pitch.js +130 -62
- package/dist/navigation-instruments/pitch/pitch.js.map +1 -1
- package/dist/navigation-instruments/pitch-roll/pitch-roll.d.ts +7 -0
- package/dist/navigation-instruments/pitch-roll/pitch-roll.d.ts.map +1 -1
- package/dist/navigation-instruments/pitch-roll/pitch-roll.js +58 -2
- package/dist/navigation-instruments/pitch-roll/pitch-roll.js.map +1 -1
- package/dist/navigation-instruments/readout/readout.css.js +4 -0
- package/dist/navigation-instruments/readout/readout.css.js.map +1 -1
- package/dist/navigation-instruments/roll/roll.d.ts +37 -0
- package/dist/navigation-instruments/roll/roll.d.ts.map +1 -1
- package/dist/navigation-instruments/roll/roll.js +119 -63
- package/dist/navigation-instruments/roll/roll.js.map +1 -1
- package/dist/navigation-instruments/rot-sector/rot-sector.d.ts +15 -0
- package/dist/navigation-instruments/rot-sector/rot-sector.d.ts.map +1 -1
- package/dist/navigation-instruments/rot-sector/rot-sector.js +53 -1
- package/dist/navigation-instruments/rot-sector/rot-sector.js.map +1 -1
- package/dist/navigation-instruments/watch/tickmark.d.ts +2 -1
- package/dist/navigation-instruments/watch/tickmark.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/tickmark.js +24 -4
- package/dist/navigation-instruments/watch/tickmark.js.map +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts +23 -1
- package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/watch.js +48 -20
- package/dist/navigation-instruments/watch/watch.js.map +1 -1
- package/package.json +1 -1
|
@@ -46,12 +46,22 @@ export declare class ObcInstrumentRadial extends ObcInstrumentRadial_base {
|
|
|
46
46
|
advices: GaugeRadialAdvice[];
|
|
47
47
|
clipTop: number;
|
|
48
48
|
clipBottom: number;
|
|
49
|
+
clipLeft: number;
|
|
50
|
+
clipRight: number;
|
|
51
|
+
/**
|
|
52
|
+
* Place the horizontal end labels (±90°, e.g. min/max) below the tick instead
|
|
53
|
+
* of beside it — the "Max-min" placement from the radial label model
|
|
54
|
+
* (External / Internal / Max-min). See PR #903 / design discussion.
|
|
55
|
+
*/
|
|
56
|
+
endLabelsMaxMin: boolean;
|
|
49
57
|
zoomToFitArc: boolean;
|
|
50
58
|
private _radiusOffset;
|
|
51
59
|
private _arcFrame;
|
|
52
60
|
private get clampedValue();
|
|
53
61
|
private get minAngle();
|
|
54
62
|
private get maxAngle();
|
|
63
|
+
private mapAngle;
|
|
64
|
+
private get safeClips();
|
|
55
65
|
private get _derivedNeedleColor();
|
|
56
66
|
private get _derivedBarColor();
|
|
57
67
|
render(): import('lit-html').TemplateResult<1>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-radial.d.ts","sourceRoot":"","sources":["../../../src/building-blocks/instrument-radial/instrument-radial.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,UAAU,EAAqB,MAAM,KAAK,CAAC;AAGxD,OAAO,EAEL,UAAU,EAEX,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EAAC,QAAQ,EAAC,MAAM,gDAAgD,CAAC;AAExE,OAAO,EAAC,aAAa,EAAC,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"instrument-radial.d.ts","sourceRoot":"","sources":["../../../src/building-blocks/instrument-radial/instrument-radial.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,UAAU,EAAqB,MAAM,KAAK,CAAC;AAGxD,OAAO,EAEL,UAAU,EAEX,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EAAC,QAAQ,EAAC,MAAM,gDAAgD,CAAC;AAExE,OAAO,EAAC,aAAa,EAAC,MAAM,gDAAgD,CAAC;AAC7E,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,uCAAuC,CAAC;AAehF,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;;AA8ED,qBACa,mBAAoB,SAAQ,wBAAyB;IAKtC,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IAEtC,KAAK,SAAK;IACV,QAAQ,SAAO;IACf,QAAQ,SAAK;IACT,QAAQ,EAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAS;IACvD;;;OAGG;IACuB,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC3E;;;OAGG;IACuB,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAM;IAC7E;;;OAGG;IACuB,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAC1D;IACc,IAAI,EAAE,kBAAkB,CACtB;IACF,UAAU,EAAE,kBAAkB,CAC5B;IACD,eAAe,EAAE,OAAO,CAAS;IAClC,aAAa,EAAE,aAAa,CAC9B;IACmB,OAAO,EAAE,iBAAiB,EAAE,CAAM;IACnD,OAAO,EAAE,MAAM,CAAK;IACpB,UAAU,EAAE,MAAM,CAAK;IACvB,QAAQ,EAAE,MAAM,CAAK;IACrB,SAAS,EAAE,MAAM,CAAK;IAChD;;;;OAIG;IACwB,eAAe,EAAE,OAAO,CAAS;IACjC,YAAY,EAAE,OAAO,CAAS;IAEzD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,SAAS,CAAgC;IAEjD,OAAO,KAAK,YAAY,GAIvB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAID,OAAO,CAAC,QAAQ;IAWhB,OAAO,KAAK,SAAS,GAOpB;IAED,OAAO,KAAK,mBAAmB,GAU9B;IAED,OAAO,KAAK,gBAAgB,GAe3B;IAEQ,MAAM;IA8Ff,OAAO,KAAK,OAAO,GAsBlB;IAED,IAAI,SAAS,IAAI,QAAQ,EAAE,CA6G1B;IAED,OAAO,KAAK,QAAQ,GAoBnB;IAED,OAAgB,MAAM,0BAmCpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,uBAAuB,EAAE,mBAAmB,CAAC;KAC9C;CACF"}
|
|
@@ -17,12 +17,17 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
17
17
|
if (kind && result) __defProp(target, key, result);
|
|
18
18
|
return result;
|
|
19
19
|
};
|
|
20
|
+
const WATCH_DEFAULT_VIEWBOX = 448;
|
|
20
21
|
var ObcGaugeRadialType = /* @__PURE__ */ ((ObcGaugeRadialType2) => {
|
|
21
22
|
ObcGaugeRadialType2["filled"] = "filled";
|
|
22
23
|
ObcGaugeRadialType2["bar"] = "bar";
|
|
23
24
|
ObcGaugeRadialType2["needle"] = "needle";
|
|
24
25
|
return ObcGaugeRadialType2;
|
|
25
26
|
})(ObcGaugeRadialType || {});
|
|
27
|
+
const NEEDLE_TIP_RADIUS = 160;
|
|
28
|
+
const NEEDLE_TIP_GAP = 5;
|
|
29
|
+
const NEEDLE_WIDTH = 8;
|
|
30
|
+
const NEEDLE_HUB_RADIUS = 16;
|
|
26
31
|
function rangeIncludesZero(minValue, maxValue) {
|
|
27
32
|
return minValue <= 0 && maxValue >= 0;
|
|
28
33
|
}
|
|
@@ -38,6 +43,31 @@ function strongerTickmarkType(existing, candidate) {
|
|
|
38
43
|
};
|
|
39
44
|
return priority[candidate] > priority[existing] ? candidate : existing;
|
|
40
45
|
}
|
|
46
|
+
function clampClipPercent(n) {
|
|
47
|
+
return Number.isFinite(n) ? Math.min(Math.max(n, 0), 100) : 0;
|
|
48
|
+
}
|
|
49
|
+
function normalizeClips(clips) {
|
|
50
|
+
let top = clampClipPercent(clips.top);
|
|
51
|
+
let bottom = clampClipPercent(clips.bottom);
|
|
52
|
+
let left = clampClipPercent(clips.left);
|
|
53
|
+
let right = clampClipPercent(clips.right);
|
|
54
|
+
if (top + bottom >= 100) {
|
|
55
|
+
top = 0;
|
|
56
|
+
bottom = 0;
|
|
57
|
+
}
|
|
58
|
+
if (left + right >= 100) {
|
|
59
|
+
left = 0;
|
|
60
|
+
right = 0;
|
|
61
|
+
}
|
|
62
|
+
return { top, bottom, left, right };
|
|
63
|
+
}
|
|
64
|
+
function defaultGaugeAngle(value, minValue, maxValue) {
|
|
65
|
+
const span = maxValue - minValue;
|
|
66
|
+
if (!Number.isFinite(span) || span <= 0) {
|
|
67
|
+
return -135;
|
|
68
|
+
}
|
|
69
|
+
return (value - minValue) / span * 270 - 135;
|
|
70
|
+
}
|
|
41
71
|
let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
42
72
|
constructor() {
|
|
43
73
|
super(...arguments);
|
|
@@ -57,6 +87,9 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
57
87
|
this.advices = [];
|
|
58
88
|
this.clipTop = 0;
|
|
59
89
|
this.clipBottom = 0;
|
|
90
|
+
this.clipLeft = 0;
|
|
91
|
+
this.clipRight = 0;
|
|
92
|
+
this.endLabelsMaxMin = false;
|
|
60
93
|
this.zoomToFitArc = false;
|
|
61
94
|
this._radiusOffset = 0;
|
|
62
95
|
}
|
|
@@ -66,10 +99,27 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
66
99
|
return Math.max(lowerBound, Math.min(this.value, upperBound));
|
|
67
100
|
}
|
|
68
101
|
get minAngle() {
|
|
69
|
-
return this.
|
|
102
|
+
return this.mapAngle(this.minValue);
|
|
70
103
|
}
|
|
71
104
|
get maxAngle() {
|
|
72
|
-
return this.
|
|
105
|
+
return this.mapAngle(this.maxValue);
|
|
106
|
+
}
|
|
107
|
+
// Map a value to an angle via the consumer's `getAngle`, guarding a missing
|
|
108
|
+
// or non-finite mapping so a misconfigured consumer can't emit NaN geometry.
|
|
109
|
+
mapAngle(value) {
|
|
110
|
+
const fn = this.getAngle;
|
|
111
|
+
const angle = typeof fn === "function" ? fn(value) : defaultGaugeAngle(value, this.minValue, this.maxValue);
|
|
112
|
+
return Number.isFinite(angle) ? angle : 0;
|
|
113
|
+
}
|
|
114
|
+
// Clamped clips, reused for the overlay viewBox and the clips forwarded to
|
|
115
|
+
// obc-watch.
|
|
116
|
+
get safeClips() {
|
|
117
|
+
return normalizeClips({
|
|
118
|
+
top: this.clipTop,
|
|
119
|
+
bottom: this.clipBottom,
|
|
120
|
+
left: this.clipLeft,
|
|
121
|
+
right: this.clipRight
|
|
122
|
+
});
|
|
73
123
|
}
|
|
74
124
|
get _derivedNeedleColor() {
|
|
75
125
|
if (this.state === InstrumentState.loading || this.state === InstrumentState.off) {
|
|
@@ -90,12 +140,12 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
90
140
|
const barColor = this.barColor ?? this._derivedBarColor;
|
|
91
141
|
const barStartValue = Math.max(this.minValue, Math.min(0, this.maxValue));
|
|
92
142
|
const value = this.clampedValue;
|
|
93
|
-
const setpointAngle = this.setpoint !== void 0 ? this.
|
|
94
|
-
const newSetpointAngle = this.newSetpoint !== void 0 ? this.
|
|
143
|
+
const setpointAngle = this.setpoint !== void 0 ? this.mapAngle(this.setpoint) : void 0;
|
|
144
|
+
const newSetpointAngle = this.newSetpoint !== void 0 ? this.mapAngle(this.newSetpoint) : void 0;
|
|
95
145
|
const barAreas = this.type === "needle" ? [] : [
|
|
96
146
|
{
|
|
97
|
-
startAngle: this.
|
|
98
|
-
endAngle: this.
|
|
147
|
+
startAngle: this.mapAngle(barStartValue),
|
|
148
|
+
endAngle: this.mapAngle(value),
|
|
99
149
|
fillColor: barColor
|
|
100
150
|
}
|
|
101
151
|
];
|
|
@@ -108,6 +158,7 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
108
158
|
}
|
|
109
159
|
];
|
|
110
160
|
const watchCircleType = this.type === "needle" ? WatchCircleType.single : WatchCircleType.double;
|
|
161
|
+
const clips = this.safeClips;
|
|
111
162
|
let viewBox;
|
|
112
163
|
if (this.zoomToFitArc) {
|
|
113
164
|
const ext = 48;
|
|
@@ -119,16 +170,18 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
119
170
|
extension: ext,
|
|
120
171
|
targetSize
|
|
121
172
|
});
|
|
122
|
-
viewBox = frame.viewBox;
|
|
123
173
|
this._radiusOffset = frame.radiusOffset;
|
|
174
|
+
viewBox = frame.viewBox;
|
|
124
175
|
this._arcFrame = frame;
|
|
125
176
|
} else {
|
|
126
177
|
this._radiusOffset = 0;
|
|
127
178
|
this._arcFrame = void 0;
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
|
|
179
|
+
const full = WATCH_DEFAULT_VIEWBOX;
|
|
180
|
+
const w = full * (1 - clips.left / 100 - clips.right / 100);
|
|
181
|
+
const h = full * (1 - clips.top / 100 - clips.bottom / 100);
|
|
182
|
+
const left = -full / 2 + full * clips.left / 100;
|
|
183
|
+
const top = -full / 2 + full * clips.top / 100;
|
|
184
|
+
viewBox = `${left} ${top} ${w} ${h}`;
|
|
132
185
|
}
|
|
133
186
|
return html`
|
|
134
187
|
<div class="container">
|
|
@@ -149,8 +202,11 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
149
202
|
.areas=${areas}
|
|
150
203
|
.watchCircleType=${watchCircleType}
|
|
151
204
|
.barAreas=${barAreas}
|
|
152
|
-
.clipTop=${this.zoomToFitArc ? 0 :
|
|
153
|
-
.clipBottom=${this.zoomToFitArc ? 0 :
|
|
205
|
+
.clipTop=${this.zoomToFitArc ? 0 : clips.top}
|
|
206
|
+
.clipBottom=${this.zoomToFitArc ? 0 : clips.bottom}
|
|
207
|
+
.clipLeft=${this.zoomToFitArc ? 0 : clips.left}
|
|
208
|
+
.clipRight=${this.zoomToFitArc ? 0 : clips.right}
|
|
209
|
+
.endLabelsMaxMin=${this.endLabelsMaxMin}
|
|
154
210
|
.zoomToFitArc=${this.zoomToFitArc}
|
|
155
211
|
.arcFrame=${this._arcFrame}
|
|
156
212
|
></obc-watch>
|
|
@@ -166,14 +222,14 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
166
222
|
const rOff = this._radiusOffset;
|
|
167
223
|
const value = this.clampedValue;
|
|
168
224
|
if (this.type === "needle") {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
<rect x="
|
|
172
|
-
<
|
|
225
|
+
const tipY = 256 - (NEEDLE_TIP_RADIUS - NEEDLE_TIP_GAP) - rOff;
|
|
226
|
+
return svg`<g transform="rotate(${this.mapAngle(value)}) translate(-256, -256)">
|
|
227
|
+
<rect x="${256 - NEEDLE_WIDTH / 2}" y="${tipY}" width="${NEEDLE_WIDTH}" height="${256 - tipY}" rx="${NEEDLE_WIDTH / 2}" fill=${needleColor} stroke=${needleColor}/>
|
|
228
|
+
<circle cx="256" cy="256" r="${NEEDLE_HUB_RADIUS}" fill=${needleColor}/>
|
|
173
229
|
</g>
|
|
174
230
|
`;
|
|
175
231
|
} else {
|
|
176
|
-
return svg`<g transform="rotate(${this.
|
|
232
|
+
return svg`<g transform="rotate(${this.mapAngle(value)}) translate(-256, -256)">
|
|
177
233
|
<rect x="252" y="${96 - rOff}" width="8" height="48" rx="4" fill=${needleColor} stroke="var(--border-silhouette-color)"/>
|
|
178
234
|
</g>
|
|
179
235
|
`;
|
|
@@ -196,7 +252,7 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
196
252
|
return;
|
|
197
253
|
}
|
|
198
254
|
tickmarksByValue.set(normalizedValue, {
|
|
199
|
-
angle: this.
|
|
255
|
+
angle: this.mapAngle(normalizedValue),
|
|
200
256
|
type,
|
|
201
257
|
text
|
|
202
258
|
});
|
|
@@ -256,8 +312,8 @@ let ObcInstrumentRadial = class extends SetpointMixin(LitElement) {
|
|
|
256
312
|
get _advices() {
|
|
257
313
|
const value = this.clampedValue;
|
|
258
314
|
return this.advices.map((advice) => {
|
|
259
|
-
const minAngle = this.
|
|
260
|
-
const maxAngle = this.
|
|
315
|
+
const minAngle = this.mapAngle(advice.minValue);
|
|
316
|
+
const maxAngle = this.mapAngle(advice.maxValue);
|
|
261
317
|
let state = advice.hinted ? AdviceState.hinted : AdviceState.regular;
|
|
262
318
|
if (value >= advice.minValue && value <= advice.maxValue) {
|
|
263
319
|
state = AdviceState.triggered;
|
|
@@ -366,6 +422,15 @@ __decorateClass([
|
|
|
366
422
|
__decorateClass([
|
|
367
423
|
property({ type: Number })
|
|
368
424
|
], ObcInstrumentRadial.prototype, "clipBottom", 2);
|
|
425
|
+
__decorateClass([
|
|
426
|
+
property({ type: Number })
|
|
427
|
+
], ObcInstrumentRadial.prototype, "clipLeft", 2);
|
|
428
|
+
__decorateClass([
|
|
429
|
+
property({ type: Number })
|
|
430
|
+
], ObcInstrumentRadial.prototype, "clipRight", 2);
|
|
431
|
+
__decorateClass([
|
|
432
|
+
property({ type: Boolean })
|
|
433
|
+
], ObcInstrumentRadial.prototype, "endLabelsMaxMin", 2);
|
|
369
434
|
__decorateClass([
|
|
370
435
|
property({ type: Boolean })
|
|
371
436
|
], ObcInstrumentRadial.prototype, "zoomToFitArc", 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-radial.js","sources":["../../../src/building-blocks/instrument-radial/instrument-radial.ts"],"sourcesContent":["import {css, LitElement, html, svg, nothing} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {customElement} from '../../decorator.js';\nimport {\n AdviceState,\n AdviceType,\n AngleAdviceRaw,\n} from '../../navigation-instruments/watch/advice.js';\nimport {WatchCircleType} from '../../navigation-instruments/watch/watch.js';\nimport {Tickmark} from '../../navigation-instruments/watch/tickmark.js';\nimport {TickmarkType} from '../../navigation-instruments/watch/tickmark.js';\nimport {TickmarkStyle} from '../../navigation-instruments/watch/tickmark.js';\nimport {InstrumentState, Priority} from '../../navigation-instruments/types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n} from '../../navigation-instruments/watch/watch.js';\nimport {\n computeZoomToFitArcFrame,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\n}\n\nexport interface GaugeRadialAdvice {\n minValue: number;\n maxValue: number;\n type: AdviceType;\n hinted: boolean;\n}\n\nfunction rangeIncludesZero(minValue: number, maxValue: number): boolean {\n return minValue <= 0 && maxValue >= 0;\n}\n\nfunction strongerTickmarkType(\n existing: TickmarkType,\n candidate: TickmarkType\n): TickmarkType {\n const priority: Record<TickmarkType, number> = {\n [TickmarkType.zeroLineThick]: 6,\n [TickmarkType.zeroLine]: 5,\n [TickmarkType.main]: 4,\n [TickmarkType.primary]: 3,\n [TickmarkType.secondary]: 2,\n [TickmarkType.tertiary]: 1,\n [TickmarkType.textOnly]: 0,\n };\n\n return priority[candidate] > priority[existing] ? candidate : existing;\n}\n\n@customElement('obc-instrument-radial')\nexport class ObcInstrumentRadial extends SetpointMixin(LitElement) {\n // setpoint, newSetpoint, atSetpoint, touching, autoAtSetpoint,\n // autoAtSetpointDeadband, setpointAtZeroDeadband, setpointOverride\n // — all inherited from SetpointMixin\n\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n\n @property({type: Number}) value = 0;\n @property({type: Number}) maxValue = 100;\n @property({type: Number}) minValue = 0;\n @property({attribute: false}) getAngle!: (v: number) => number;\n @property({type: String}) needleColor: string | undefined;\n @property({type: String}) barColor: string | undefined;\n @property({type: Boolean}) showLabels: boolean = false;\n /**\n * Interval for primary tickmarks in value units.\n * When undefined or <= 0, no primary tickmarks are shown.\n */\n @property({type: Number}) primaryTickmarkInterval: number | undefined = 50;\n /**\n * Interval for secondary tickmarks in value units.\n * When undefined or <= 0, no secondary tickmarks are shown.\n */\n @property({type: Number}) secondaryTickmarkInterval: number | undefined = 10;\n /**\n * Interval for tertiary tickmarks in value units.\n * When undefined or <= 0, no tertiary tickmarks are shown.\n */\n @property({type: Number}) tertiaryTickmarkInterval: number | undefined =\n undefined;\n @property({type: String}) type: ObcGaugeRadialType =\n ObcGaugeRadialType.filled;\n @property({type: String}) needleType: ObcGaugeRadialType =\n ObcGaugeRadialType.filled;\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n @property({type: Number}) clipTop: number = 0; // in percent of height\n @property({type: Number}) clipBottom: number = 0; // in percent of height\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n\n private _radiusOffset = 0;\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get clampedValue(): number {\n const lowerBound = Math.min(this.minValue, this.maxValue);\n const upperBound = Math.max(this.minValue, this.maxValue);\n return Math.max(lowerBound, Math.min(this.value, upperBound));\n }\n\n private get minAngle(): number {\n return this.getAngle(this.minValue);\n }\n\n private get maxAngle(): number {\n return this.getAngle(this.maxValue);\n }\n\n private get _derivedNeedleColor(): string {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'transparent';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get _derivedBarColor(): string {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'transparent';\n }\n if (this.type === ObcGaugeRadialType.filled) {\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n override render() {\n const barColor = this.barColor ?? this._derivedBarColor;\n const barStartValue = Math.max(this.minValue, Math.min(0, this.maxValue));\n const value = this.clampedValue;\n const setpointAngle =\n this.setpoint !== undefined ? this.getAngle(this.setpoint) : undefined;\n const newSetpointAngle =\n this.newSetpoint !== undefined\n ? this.getAngle(this.newSetpoint)\n : undefined;\n\n const barAreas =\n this.type === ObcGaugeRadialType.needle\n ? []\n : [\n {\n startAngle: this.getAngle(barStartValue),\n endAngle: this.getAngle(value),\n fillColor: barColor,\n },\n ];\n\n const areas = [\n {\n startAngle: this.minAngle,\n endAngle: this.maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const watchCircleType =\n this.type === ObcGaugeRadialType.needle\n ? WatchCircleType.single\n : WatchCircleType.double;\n\n let viewBox: string;\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const frame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(watchCircleType),\n extension: ext,\n targetSize,\n });\n viewBox = frame.viewBox;\n this._radiusOffset = frame.radiusOffset;\n this._arcFrame = frame;\n } else {\n this._radiusOffset = 0;\n this._arcFrame = undefined;\n const width = 448;\n const height = width * (1 - this.clipTop / 100 - this.clipBottom / 100);\n const top = -width / 2 + (width * this.clipTop) / 100;\n viewBox = `${-width / 2} ${top} ${width} ${height}`;\n }\n\n return html`\n <div class=\"container\">\n <obc-watch\n .state=${this.state}\n .priority=${this.priority}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${newSetpointAngle}\n .atAngleSetpoint=${this.computeAtSetpoint(value)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .padding=${48}\n .tickmarks=${this.tickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .advices=${this._advices}\n .areas=${areas}\n .watchCircleType=${watchCircleType}\n .barAreas=${barAreas}\n .clipTop=${this.zoomToFitArc ? 0 : this.clipTop}\n .clipBottom=${this.zoomToFitArc ? 0 : this.clipBottom}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n ></obc-watch>\n <svg class=\"gauge-radial\" viewBox=${viewBox}>${this._needle}</svg>\n </div>\n `;\n }\n\n private get _needle() {\n if (this.type === ObcGaugeRadialType.filled) {\n return nothing;\n }\n const needleColor = this.needleColor ?? this._derivedNeedleColor;\n const rOff = this._radiusOffset;\n const value = this.clampedValue;\n if (this.type === ObcGaugeRadialType.needle) {\n return svg`<g transform=\"rotate(${this.getAngle(value)}) translate(-256, -256)\">\n <circle cx=\"256\" cy=\"256\" r=\"14\" fill=${needleColor}/>\n <rect x=\"250\" y=\"${96 - rOff}\" width=\"12\" height=\"${192 + rOff}\" rx=\"6\" fill=${needleColor}/>\n <rect x=\"252\" y=\"${98 - rOff}\" width=\"8\" height=\"${188 + rOff}\" rx=\"4\" stroke=${needleColor} fill=${needleColor} stroke-width=\"4\"/>\n </g>\n`;\n } else {\n return svg`<g transform=\"rotate(${this.getAngle(value)}) translate(-256, -256)\">\n<rect x=\"252\" y=\"${96 - rOff}\" width=\"8\" height=\"48\" rx=\"4\" fill=${needleColor} stroke=\"var(--border-silhouette-color)\"/>\n</g>\n `;\n }\n }\n\n get tickmarks(): Tickmark[] {\n const tickmarksByValue = new Map<number, Tickmark>();\n const normalizeValue = (value: number) =>\n Math.abs(value) < 1e-9 ? 0 : Number(value.toFixed(6));\n\n const upsertTickmark = (\n value: number,\n type: TickmarkType,\n text?: string\n ) => {\n if (\n !Number.isFinite(value) ||\n value < this.minValue ||\n value > this.maxValue\n ) {\n return;\n }\n\n const normalizedValue = normalizeValue(value);\n const existing = tickmarksByValue.get(normalizedValue);\n if (existing) {\n existing.type = strongerTickmarkType(existing.type, type);\n if (text !== undefined) {\n existing.text = text;\n }\n return;\n }\n\n tickmarksByValue.set(normalizedValue, {\n angle: this.getAngle(normalizedValue),\n type,\n text,\n });\n };\n\n const addTickmarksAtInterval = (\n interval: number | undefined,\n type: TickmarkType,\n withLabels = false\n ) => {\n if (\n interval === undefined ||\n interval <= 0 ||\n !Number.isFinite(interval)\n ) {\n return;\n }\n\n const epsilon = Math.abs(interval) * 1e-6;\n const startValue =\n Math.ceil((this.minValue - epsilon) / interval) * interval;\n\n for (\n let value = startValue;\n value < this.maxValue - epsilon;\n value += interval\n ) {\n const normalizedValue = normalizeValue(value);\n if (\n normalizedValue <= this.minValue + epsilon ||\n normalizedValue >= this.maxValue - epsilon\n ) {\n continue;\n }\n\n upsertTickmark(\n normalizedValue,\n type,\n withLabels && this.showLabels ? normalizedValue.toString() : undefined\n );\n }\n };\n\n addTickmarksAtInterval(\n this.primaryTickmarkInterval,\n TickmarkType.primary,\n true\n );\n addTickmarksAtInterval(\n this.secondaryTickmarkInterval,\n TickmarkType.secondary\n );\n addTickmarksAtInterval(\n this.tertiaryTickmarkInterval,\n TickmarkType.tertiary\n );\n\n if (rangeIncludesZero(this.minValue, this.maxValue)) {\n upsertTickmark(\n 0,\n this.minValue < 0 ? TickmarkType.main : TickmarkType.textOnly,\n this.showLabels ? '0' : undefined\n );\n }\n\n if (this.showLabels) {\n upsertTickmark(\n this.minValue,\n TickmarkType.textOnly,\n this.minValue.toString()\n );\n upsertTickmark(\n this.maxValue,\n TickmarkType.textOnly,\n this.maxValue.toString()\n );\n }\n\n return [...tickmarksByValue.values()].sort((a, b) => a.angle - b.angle);\n }\n\n private get _advices(): AngleAdviceRaw[] {\n const value = this.clampedValue;\n\n return this.advices.map((advice) => {\n const minAngle = this.getAngle(advice.minValue);\n const maxAngle = this.getAngle(advice.maxValue);\n let state = advice.hinted ? AdviceState.hinted : AdviceState.regular;\n if (value >= advice.minValue && value <= advice.maxValue) {\n state = AdviceState.triggered;\n }\n\n return {\n minAngle,\n maxAngle,\n type: advice.type,\n state,\n hideMinTickmark: advice.minValue === this.minValue,\n hideMaxTickmark: advice.maxValue === this.maxValue,\n };\n });\n }\n\n static override styles = css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n obc-watch {\n anchor-name: --watch;\n }\n\n .speed-gauge-value {\n position: absolute;\n top: clamp(\n 70%,\n calc(80% - (anchor-size(--watch height) - 200px) * 0.2),\n 80%\n );\n left: 50%;\n transform: translateX(-50%);\n width: fit-content;\n height: fit-content;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-instrument-radial': ObcInstrumentRadial;\n }\n}\n"],"names":["ObcGaugeRadialType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instrument-radial.js","sources":["../../../src/building-blocks/instrument-radial/instrument-radial.ts"],"sourcesContent":["import {css, LitElement, html, svg, nothing} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {customElement} from '../../decorator.js';\nimport {\n AdviceState,\n AdviceType,\n AngleAdviceRaw,\n} from '../../navigation-instruments/watch/advice.js';\nimport {WatchCircleType} from '../../navigation-instruments/watch/watch.js';\nimport {Tickmark} from '../../navigation-instruments/watch/tickmark.js';\nimport {TickmarkType} from '../../navigation-instruments/watch/tickmark.js';\nimport {TickmarkStyle} from '../../navigation-instruments/watch/tickmark.js';\nimport {InstrumentState, Priority} from '../../navigation-instruments/types.js';\nimport {SetpointMixin} from '../../svghelpers/setpoint-mixin.js';\nimport {\n OUTER_RING_RADIUS,\n innerRingRadiusFor,\n} from '../../navigation-instruments/watch/watch.js';\nimport {\n computeZoomToFitArcFrame,\n type ZoomToFitArcFrame,\n} from '../../svghelpers/arc-frame.js';\n\n// Must match obc-watch's un-zoomed viewBox `(176 + getPadding()) * 2`\n// (default padding 48 → 448); instrument-radial overlays obc-watch 1:1.\nconst WATCH_DEFAULT_VIEWBOX = 448;\n\nexport enum ObcGaugeRadialType {\n filled = 'filled',\n bar = 'bar',\n needle = 'needle',\n}\n\nexport interface GaugeRadialAdvice {\n minValue: number;\n maxValue: number;\n type: AdviceType;\n hinted: boolean;\n}\n\nconst NEEDLE_TIP_RADIUS = 160;\nconst NEEDLE_TIP_GAP = 5; // tip stops this far short of the scale\nconst NEEDLE_WIDTH = 8;\nconst NEEDLE_HUB_RADIUS = 16;\n\nfunction rangeIncludesZero(minValue: number, maxValue: number): boolean {\n return minValue <= 0 && maxValue >= 0;\n}\n\nfunction strongerTickmarkType(\n existing: TickmarkType,\n candidate: TickmarkType\n): TickmarkType {\n const priority: Record<TickmarkType, number> = {\n [TickmarkType.zeroLineThick]: 6,\n [TickmarkType.zeroLine]: 5,\n [TickmarkType.main]: 4,\n [TickmarkType.primary]: 3,\n [TickmarkType.secondary]: 2,\n [TickmarkType.tertiary]: 1,\n [TickmarkType.textOnly]: 0,\n };\n\n return priority[candidate] > priority[existing] ? candidate : existing;\n}\n\ninterface Clips {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\n/** Clamp a clip percentage to [0, 100]; non-finite returns 0. */\nfunction clampClipPercent(n: number): number {\n return Number.isFinite(n) ? Math.min(Math.max(n, 0), 100) : 0;\n}\n\n/**\n * Clamp the four clips to [0, 100] and drop any opposite pair that would\n * collapse the viewBox (sum >= 100), so a bad clip can't produce a zero- or\n * negative-size box. Valid clips pass through unchanged.\n */\nfunction normalizeClips(clips: Clips): Clips {\n let top = clampClipPercent(clips.top);\n let bottom = clampClipPercent(clips.bottom);\n let left = clampClipPercent(clips.left);\n let right = clampClipPercent(clips.right);\n if (top + bottom >= 100) {\n top = 0;\n bottom = 0;\n }\n if (left + right >= 100) {\n left = 0;\n right = 0;\n }\n return {top, bottom, left, right};\n}\n\n/**\n * Fallback value-to-angle mapping when no `getAngle` is supplied: linear over\n * the historical 270° sweep (-135 to 135). Returns -135 for a non-positive or\n * non-finite span.\n */\nfunction defaultGaugeAngle(\n value: number,\n minValue: number,\n maxValue: number\n): number {\n const span = maxValue - minValue;\n if (!Number.isFinite(span) || span <= 0) {\n return -135;\n }\n return ((value - minValue) / span) * 270 - 135;\n}\n\n@customElement('obc-instrument-radial')\nexport class ObcInstrumentRadial extends SetpointMixin(LitElement) {\n // setpoint, newSetpoint, atSetpoint, touching, autoAtSetpoint,\n // autoAtSetpointDeadband, setpointAtZeroDeadband, setpointOverride\n // — all inherited from SetpointMixin\n\n @property({type: String}) state: InstrumentState = InstrumentState.active;\n @property({type: String}) priority: Priority = Priority.regular;\n\n @property({type: Number}) value = 0;\n @property({type: Number}) maxValue = 100;\n @property({type: Number}) minValue = 0;\n @property({attribute: false}) getAngle!: (v: number) => number;\n @property({type: String}) needleColor: string | undefined;\n @property({type: String}) barColor: string | undefined;\n @property({type: Boolean}) showLabels: boolean = false;\n /**\n * Interval for primary tickmarks in value units.\n * When undefined or <= 0, no primary tickmarks are shown.\n */\n @property({type: Number}) primaryTickmarkInterval: number | undefined = 50;\n /**\n * Interval for secondary tickmarks in value units.\n * When undefined or <= 0, no secondary tickmarks are shown.\n */\n @property({type: Number}) secondaryTickmarkInterval: number | undefined = 10;\n /**\n * Interval for tertiary tickmarks in value units.\n * When undefined or <= 0, no tertiary tickmarks are shown.\n */\n @property({type: Number}) tertiaryTickmarkInterval: number | undefined =\n undefined;\n @property({type: String}) type: ObcGaugeRadialType =\n ObcGaugeRadialType.filled;\n @property({type: String}) needleType: ObcGaugeRadialType =\n ObcGaugeRadialType.filled;\n @property({type: Boolean}) tickmarksInside: boolean = false;\n @property({type: String}) tickmarkStyle: TickmarkStyle =\n TickmarkStyle.regular;\n @property({type: Array, attribute: false}) advices: GaugeRadialAdvice[] = [];\n @property({type: Number}) clipTop: number = 0; // in percent of height\n @property({type: Number}) clipBottom: number = 0; // in percent of height\n @property({type: Number}) clipLeft: number = 0; // in percent of width\n @property({type: Number}) clipRight: number = 0; // in percent of width\n /**\n * Place the horizontal end labels (±90°, e.g. min/max) below the tick instead\n * of beside it — the \"Max-min\" placement from the radial label model\n * (External / Internal / Max-min). See PR #903 / design discussion.\n */\n @property({type: Boolean}) endLabelsMaxMin: boolean = false;\n @property({type: Boolean}) zoomToFitArc: boolean = false;\n\n private _radiusOffset = 0;\n private _arcFrame: ZoomToFitArcFrame | undefined;\n\n private get clampedValue(): number {\n const lowerBound = Math.min(this.minValue, this.maxValue);\n const upperBound = Math.max(this.minValue, this.maxValue);\n return Math.max(lowerBound, Math.min(this.value, upperBound));\n }\n\n private get minAngle(): number {\n return this.mapAngle(this.minValue);\n }\n\n private get maxAngle(): number {\n return this.mapAngle(this.maxValue);\n }\n\n // Map a value to an angle via the consumer's `getAngle`, guarding a missing\n // or non-finite mapping so a misconfigured consumer can't emit NaN geometry.\n private mapAngle(value: number): number {\n const fn = this.getAngle;\n const angle =\n typeof fn === 'function'\n ? fn(value)\n : defaultGaugeAngle(value, this.minValue, this.maxValue);\n return Number.isFinite(angle) ? angle : 0;\n }\n\n // Clamped clips, reused for the overlay viewBox and the clips forwarded to\n // obc-watch.\n private get safeClips(): Clips {\n return normalizeClips({\n top: this.clipTop,\n bottom: this.clipBottom,\n left: this.clipLeft,\n right: this.clipRight,\n });\n }\n\n private get _derivedNeedleColor(): string {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'transparent';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n\n private get _derivedBarColor(): string {\n if (\n this.state === InstrumentState.loading ||\n this.state === InstrumentState.off\n ) {\n return 'transparent';\n }\n if (this.type === ObcGaugeRadialType.filled) {\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-secondary-color)'\n : 'var(--instrument-regular-secondary-color)';\n }\n return this.priority === Priority.enhanced\n ? 'var(--instrument-enhanced-tertiary-color)'\n : 'var(--instrument-regular-tertiary-color)';\n }\n\n override render() {\n const barColor = this.barColor ?? this._derivedBarColor;\n const barStartValue = Math.max(this.minValue, Math.min(0, this.maxValue));\n const value = this.clampedValue;\n const setpointAngle =\n this.setpoint !== undefined ? this.mapAngle(this.setpoint) : undefined;\n const newSetpointAngle =\n this.newSetpoint !== undefined\n ? this.mapAngle(this.newSetpoint)\n : undefined;\n\n const barAreas =\n this.type === ObcGaugeRadialType.needle\n ? []\n : [\n {\n startAngle: this.mapAngle(barStartValue),\n endAngle: this.mapAngle(value),\n fillColor: barColor,\n },\n ];\n\n const areas = [\n {\n startAngle: this.minAngle,\n endAngle: this.maxAngle,\n roundInsideCut: true,\n roundOutsideCut: true,\n },\n ];\n\n const watchCircleType =\n this.type === ObcGaugeRadialType.needle\n ? WatchCircleType.single\n : WatchCircleType.double;\n\n const clips = this.safeClips;\n let viewBox: string;\n if (this.zoomToFitArc) {\n const ext = 48;\n const targetSize = (176 + ext) * 2;\n const frame = computeZoomToFitArcFrame({\n areas,\n outerRadius: OUTER_RING_RADIUS,\n innerRadius: innerRingRadiusFor(watchCircleType),\n extension: ext,\n targetSize,\n });\n this._radiusOffset = frame.radiusOffset;\n viewBox = frame.viewBox;\n this._arcFrame = frame;\n } else {\n this._radiusOffset = 0;\n this._arcFrame = undefined;\n const full = WATCH_DEFAULT_VIEWBOX;\n const w = full * (1 - clips.left / 100 - clips.right / 100);\n const h = full * (1 - clips.top / 100 - clips.bottom / 100);\n const left = -full / 2 + (full * clips.left) / 100;\n const top = -full / 2 + (full * clips.top) / 100;\n viewBox = `${left} ${top} ${w} ${h}`;\n }\n\n return html`\n <div class=\"container\">\n <obc-watch\n .state=${this.state}\n .priority=${this.priority}\n .angleSetpoint=${setpointAngle}\n .newAngleSetpoint=${newSetpointAngle}\n .atAngleSetpoint=${this.computeAtSetpoint(value)}\n .angleSetpointAtZeroDeadband=${this.setpointAtZeroDeadband}\n .setpointOverride=${this.setpointOverride}\n .animateSetpoint=${this.animateSetpoint}\n .padding=${48}\n .tickmarks=${this.tickmarks}\n .tickmarksInside=${this.tickmarksInside}\n .tickmarkStyle=${this.tickmarkStyle}\n .advices=${this._advices}\n .areas=${areas}\n .watchCircleType=${watchCircleType}\n .barAreas=${barAreas}\n .clipTop=${this.zoomToFitArc ? 0 : clips.top}\n .clipBottom=${this.zoomToFitArc ? 0 : clips.bottom}\n .clipLeft=${this.zoomToFitArc ? 0 : clips.left}\n .clipRight=${this.zoomToFitArc ? 0 : clips.right}\n .endLabelsMaxMin=${this.endLabelsMaxMin}\n .zoomToFitArc=${this.zoomToFitArc}\n .arcFrame=${this._arcFrame}\n ></obc-watch>\n <svg class=\"gauge-radial\" viewBox=${viewBox}>${this._needle}</svg>\n </div>\n `;\n }\n\n private get _needle() {\n if (this.type === ObcGaugeRadialType.filled) {\n return nothing;\n }\n const needleColor = this.needleColor ?? this._derivedNeedleColor;\n const rOff = this._radiusOffset;\n const value = this.clampedValue;\n if (this.type === ObcGaugeRadialType.needle) {\n // Rod runs from the value tip down to the center hub. Width is constant;\n // the tip shifts outward additively under zoom.\n const tipY = 256 - (NEEDLE_TIP_RADIUS - NEEDLE_TIP_GAP) - rOff;\n return svg`<g transform=\"rotate(${this.mapAngle(value)}) translate(-256, -256)\">\n <rect x=\"${256 - NEEDLE_WIDTH / 2}\" y=\"${tipY}\" width=\"${NEEDLE_WIDTH}\" height=\"${256 - tipY}\" rx=\"${NEEDLE_WIDTH / 2}\" fill=${needleColor} stroke=${needleColor}/>\n <circle cx=\"256\" cy=\"256\" r=\"${NEEDLE_HUB_RADIUS}\" fill=${needleColor}/>\n </g>\n`;\n } else {\n return svg`<g transform=\"rotate(${this.mapAngle(value)}) translate(-256, -256)\">\n<rect x=\"252\" y=\"${96 - rOff}\" width=\"8\" height=\"48\" rx=\"4\" fill=${needleColor} stroke=\"var(--border-silhouette-color)\"/>\n</g>\n `;\n }\n }\n\n get tickmarks(): Tickmark[] {\n const tickmarksByValue = new Map<number, Tickmark>();\n const normalizeValue = (value: number) =>\n Math.abs(value) < 1e-9 ? 0 : Number(value.toFixed(6));\n\n const upsertTickmark = (\n value: number,\n type: TickmarkType,\n text?: string\n ) => {\n if (\n !Number.isFinite(value) ||\n value < this.minValue ||\n value > this.maxValue\n ) {\n return;\n }\n\n const normalizedValue = normalizeValue(value);\n const existing = tickmarksByValue.get(normalizedValue);\n if (existing) {\n existing.type = strongerTickmarkType(existing.type, type);\n if (text !== undefined) {\n existing.text = text;\n }\n return;\n }\n\n tickmarksByValue.set(normalizedValue, {\n angle: this.mapAngle(normalizedValue),\n type,\n text,\n });\n };\n\n const addTickmarksAtInterval = (\n interval: number | undefined,\n type: TickmarkType,\n withLabels = false\n ) => {\n if (\n interval === undefined ||\n interval <= 0 ||\n !Number.isFinite(interval)\n ) {\n return;\n }\n\n const epsilon = Math.abs(interval) * 1e-6;\n const startValue =\n Math.ceil((this.minValue - epsilon) / interval) * interval;\n\n for (\n let value = startValue;\n value < this.maxValue - epsilon;\n value += interval\n ) {\n const normalizedValue = normalizeValue(value);\n if (\n normalizedValue <= this.minValue + epsilon ||\n normalizedValue >= this.maxValue - epsilon\n ) {\n continue;\n }\n\n upsertTickmark(\n normalizedValue,\n type,\n withLabels && this.showLabels ? normalizedValue.toString() : undefined\n );\n }\n };\n\n addTickmarksAtInterval(\n this.primaryTickmarkInterval,\n TickmarkType.primary,\n true\n );\n addTickmarksAtInterval(\n this.secondaryTickmarkInterval,\n TickmarkType.secondary\n );\n addTickmarksAtInterval(\n this.tertiaryTickmarkInterval,\n TickmarkType.tertiary\n );\n\n if (rangeIncludesZero(this.minValue, this.maxValue)) {\n upsertTickmark(\n 0,\n this.minValue < 0 ? TickmarkType.main : TickmarkType.textOnly,\n this.showLabels ? '0' : undefined\n );\n }\n\n if (this.showLabels) {\n upsertTickmark(\n this.minValue,\n TickmarkType.textOnly,\n this.minValue.toString()\n );\n upsertTickmark(\n this.maxValue,\n TickmarkType.textOnly,\n this.maxValue.toString()\n );\n }\n\n return [...tickmarksByValue.values()].sort((a, b) => a.angle - b.angle);\n }\n\n private get _advices(): AngleAdviceRaw[] {\n const value = this.clampedValue;\n\n return this.advices.map((advice) => {\n const minAngle = this.mapAngle(advice.minValue);\n const maxAngle = this.mapAngle(advice.maxValue);\n let state = advice.hinted ? AdviceState.hinted : AdviceState.regular;\n if (value >= advice.minValue && value <= advice.maxValue) {\n state = AdviceState.triggered;\n }\n\n return {\n minAngle,\n maxAngle,\n type: advice.type,\n state,\n hideMinTickmark: advice.minValue === this.minValue,\n hideMaxTickmark: advice.maxValue === this.maxValue,\n };\n });\n }\n\n static override styles = css`\n * {\n box-sizing: border-box;\n }\n\n .container {\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n .container > * {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n\n obc-watch {\n anchor-name: --watch;\n }\n\n .speed-gauge-value {\n position: absolute;\n top: clamp(\n 70%,\n calc(80% - (anchor-size(--watch height) - 200px) * 0.2),\n 80%\n );\n left: 50%;\n transform: translateX(-50%);\n width: fit-content;\n height: fit-content;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-instrument-radial': ObcInstrumentRadial;\n }\n}\n"],"names":["ObcGaugeRadialType"],"mappings":"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"}
|
|
@@ -22,6 +22,18 @@ const componentStyle = css`
|
|
|
22
22
|
height: 100%;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
.container > .readout {
|
|
26
|
+
left: 50%;
|
|
27
|
+
width: auto;
|
|
28
|
+
height: auto;
|
|
29
|
+
transform: translate(-50%, -50%);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
obc-readout::part(value-wrapper),
|
|
33
|
+
obc-readout::part(meta-wrapper) {
|
|
34
|
+
justify-self: center;
|
|
35
|
+
}
|
|
36
|
+
|
|
25
37
|
:host {
|
|
26
38
|
display: block;
|
|
27
39
|
width: 100%;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compass-sector.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compass-sector.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,6 +3,7 @@ import { AngleAdvice } from '../watch/advice.js';
|
|
|
3
3
|
import { RotType, RotPosition } from '../watch/watch.js';
|
|
4
4
|
import { InstrumentState, Priority } from '../types.js';
|
|
5
5
|
import '../watch/watch.js';
|
|
6
|
+
import '../readout/readout.js';
|
|
6
7
|
export { RotType, RotPosition };
|
|
7
8
|
export declare enum CompassSectorPriorityElement {
|
|
8
9
|
hdg = "hdg",
|
|
@@ -98,6 +99,12 @@ export declare class ObcCompassSector extends LitElement {
|
|
|
98
99
|
priorityElements: CompassSectorPriorityElement[];
|
|
99
100
|
tickmarksInside: boolean;
|
|
100
101
|
zoomToFitArc: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* When `true`, shows a centered `<obc-readout>` under the arc displaying the
|
|
104
|
+
* heading (label `HDG`, unit `DEG`). The value color follows the HDG entry in
|
|
105
|
+
* `priorityElements`, matching the HDG arrow.
|
|
106
|
+
*/
|
|
107
|
+
hasReadout: boolean;
|
|
101
108
|
private _headingSp;
|
|
102
109
|
private _halfFOV;
|
|
103
110
|
private _arcHalfExtent;
|
|
@@ -119,6 +126,22 @@ export declare class ObcCompassSector extends LitElement {
|
|
|
119
126
|
private get _effectiveRotDegPerMin();
|
|
120
127
|
private get _rotEndAngle();
|
|
121
128
|
private priorityFor;
|
|
129
|
+
/**
|
|
130
|
+
* Vertical placement of the readout as a percentage of the host height.
|
|
131
|
+
*
|
|
132
|
+
* With `zoomToFitArc` the arc is reframed by `computeZoomToFitArcFrame`, whose
|
|
133
|
+
* `radiusOffset`/`viewBox` depend on the arc's *absolute* orientation (which
|
|
134
|
+
* cardinal axes its bounding box crosses), not just its bend. The arc itself
|
|
135
|
+
* is always rotated back to the top, so it stays put on screen — but a
|
|
136
|
+
* frame-derived offset would swing wildly as `heading` rotates the bbox around
|
|
137
|
+
* the circle. So in zoom we use a fixed offset, which keeps the readout steady
|
|
138
|
+
* under the (stationary) arc regardless of heading.
|
|
139
|
+
*
|
|
140
|
+
* Without zoom the viewBox is the fixed, origin-symmetric 120° framing, so the
|
|
141
|
+
* geometry is orientation-independent: place the readout halfway down the inner
|
|
142
|
+
* radius from the watch center toward the arc's inner edge.
|
|
143
|
+
*/
|
|
144
|
+
private get _readoutTopPercent();
|
|
122
145
|
render(): import('lit-html').TemplateResult<1>;
|
|
123
146
|
static styles: import('lit').CSSResult;
|
|
124
147
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compass-sector.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/compass-sector/compass-sector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAgC,MAAM,KAAK,CAAC;AAG9E,OAAO,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"compass-sector.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/compass-sector/compass-sector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAgC,MAAM,KAAK,CAAC;AAG9E,OAAO,mBAAmB,CAAC;AAC3B,OAAO,uBAAuB,CAAC;AAI/B,OAAO,EAAc,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAKL,OAAO,EACP,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EAAC,eAAe,EAAE,QAAQ,EAAC,MAAM,aAAa,CAAC;AACtD,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,CAAC;AAE9B,oBAAY,4BAA4B;IACtC,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,GAAG,QAAQ;CACZ;AA+BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBACa,gBAAiB,SAAQ,UAAU;IACpB,OAAO,SAAK;IACZ,gBAAgB,SAAK;IAErB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IACtC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,iBAAiB,EAAE,OAAO,CAAS;IACpC,6BAA6B,EAAE,MAAM,CAAO;IAC3C,uBAAuB,EAAE,OAAO,CAAS;IACvB,qBAAqB,UAAQ;IAChD,6BAA6B,EAAE,MAAM,CAAK;IACzC,eAAe,EAAE,OAAO,CAAS;IACjC,QAAQ,EAAE,OAAO,CAAS;IACV,cAAc,EAAE,WAAW,EAAE,CAAM;IAEpD,MAAM,EAAE,MAAM,CAAM;IAEpB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,WAAW,CAA2B;IAC7E;;;;;OAKG;IACuB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IACzE;;;;OAIG;IACuB,qBAAqB,EAAE,MAAM,CAAM;IAC7D;;;;OAIG;IACuB,kBAAkB,EAAE,MAAM,CAAK;IACzD;;;;;;;OAOG;IACuB,WAAW,EAAE,MAAM,CAAM;IACxB,gBAAgB,EAAE,OAAO,CAAS;IACnC,iBAAiB,EAAE,MAAM,CAAyB;IAElD,KAAK,EAAE,eAAe,CAA0B;IAChD,QAAQ,EAAE,QAAQ,CAAoB;IAEhE,gBAAgB,EAAE,4BAA4B,EAAE,CAE9C;IACyB,eAAe,EAAE,OAAO,CAAS;IACjC,YAAY,EAAE,OAAO,CAAS;IACzD;;;;OAIG;IACwB,UAAU,EAAE,OAAO,CAAS;IAEvD,OAAO,CAAC,UAAU,CAGf;IAGH,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,cAAc,CAAwB;IAErC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IA8DzC,oBAAoB,IAAI,IAAI;IASrC,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,eAAe;IAmDvB,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IAgBrB,OAAO,KAAK,sBAAsB,GAEjC;IAED,OAAO,KAAK,YAAY,GAKvB;IAED,OAAO,CAAC,WAAW;IAOnB;;;;;;;;;;;;;;OAcG;IACH,OAAO,KAAK,kBAAkB,GAU7B;IAMQ,MAAM;IAkGf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,gBAAgB,CAAC;KACxC;CACF"}
|
|
@@ -2,6 +2,7 @@ import { unsafeCSS, LitElement, nothing, svg, html } from "lit";
|
|
|
2
2
|
import { property } from "lit/decorators.js";
|
|
3
3
|
import componentStyle from "./compass-sector.css.js";
|
|
4
4
|
import { WatchCircleType, innerRingRadiusFor, OUTER_RING_RADIUS } from "../watch/watch.js";
|
|
5
|
+
import { ReadoutVariant, ReadoutDirection } from "../readout/readout.js";
|
|
5
6
|
import { TickmarkType, TickmarkStyle } from "../watch/tickmark.js";
|
|
6
7
|
import { arrow, ArrowStyle } from "../compass/arrow.js";
|
|
7
8
|
import { AdviceState } from "../watch/advice.js";
|
|
@@ -75,6 +76,7 @@ let ObcCompassSector = class extends LitElement {
|
|
|
75
76
|
];
|
|
76
77
|
this.tickmarksInside = false;
|
|
77
78
|
this.zoomToFitArc = false;
|
|
79
|
+
this.hasReadout = false;
|
|
78
80
|
this._headingSp = new SetpointBundle({
|
|
79
81
|
angularWraparound: true,
|
|
80
82
|
onAnimationEnd: () => this.requestUpdate()
|
|
@@ -262,6 +264,32 @@ let ObcCompassSector = class extends LitElement {
|
|
|
262
264
|
const selected = Array.isArray(this.priorityElements) ? this.priorityElements : [];
|
|
263
265
|
return selected.includes(element) ? this.priority : Priority.regular;
|
|
264
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Vertical placement of the readout as a percentage of the host height.
|
|
269
|
+
*
|
|
270
|
+
* With `zoomToFitArc` the arc is reframed by `computeZoomToFitArcFrame`, whose
|
|
271
|
+
* `radiusOffset`/`viewBox` depend on the arc's *absolute* orientation (which
|
|
272
|
+
* cardinal axes its bounding box crosses), not just its bend. The arc itself
|
|
273
|
+
* is always rotated back to the top, so it stays put on screen — but a
|
|
274
|
+
* frame-derived offset would swing wildly as `heading` rotates the bbox around
|
|
275
|
+
* the circle. So in zoom we use a fixed offset, which keeps the readout steady
|
|
276
|
+
* under the (stationary) arc regardless of heading.
|
|
277
|
+
*
|
|
278
|
+
* Without zoom the viewBox is the fixed, origin-symmetric 120° framing, so the
|
|
279
|
+
* geometry is orientation-independent: place the readout halfway down the inner
|
|
280
|
+
* radius from the watch center toward the arc's inner edge.
|
|
281
|
+
*/
|
|
282
|
+
get _readoutTopPercent() {
|
|
283
|
+
if (this.zoomToFitArc) {
|
|
284
|
+
return 70;
|
|
285
|
+
}
|
|
286
|
+
const [, vy, , vh] = this._cachedViewBox.split(" ").map(Number);
|
|
287
|
+
if (!vh || Number.isNaN(vy)) {
|
|
288
|
+
return 50;
|
|
289
|
+
}
|
|
290
|
+
const anchorY = -INNER_RADIUS * 0.5;
|
|
291
|
+
return Math.round((anchorY - vy) / vh * 1e3) / 10;
|
|
292
|
+
}
|
|
265
293
|
// ---------------------------------------------------------------------------
|
|
266
294
|
// Render
|
|
267
295
|
// ---------------------------------------------------------------------------
|
|
@@ -343,6 +371,22 @@ let ObcCompassSector = class extends LitElement {
|
|
|
343
371
|
rOff
|
|
344
372
|
)}
|
|
345
373
|
</svg>
|
|
374
|
+
${this.hasReadout ? html`<div class="readout" style="top: ${this._readoutTopPercent}%">
|
|
375
|
+
<obc-readout
|
|
376
|
+
.variant=${ReadoutVariant.enhanced}
|
|
377
|
+
.direction=${ReadoutDirection.vertical}
|
|
378
|
+
.hasSetpoint=${false}
|
|
379
|
+
.hasAdvice=${false}
|
|
380
|
+
.value=${this.heading}
|
|
381
|
+
.fractionDigits=${0}
|
|
382
|
+
.valuePriority=${this.priorityFor(
|
|
383
|
+
"hdg"
|
|
384
|
+
/* hdg */
|
|
385
|
+
)}
|
|
386
|
+
label="HDG"
|
|
387
|
+
unit="DEG"
|
|
388
|
+
></obc-readout>
|
|
389
|
+
</div>` : nothing}
|
|
346
390
|
</div>
|
|
347
391
|
`;
|
|
348
392
|
}
|
|
@@ -426,6 +470,9 @@ __decorateClass([
|
|
|
426
470
|
__decorateClass([
|
|
427
471
|
property({ type: Boolean })
|
|
428
472
|
], ObcCompassSector.prototype, "zoomToFitArc", 2);
|
|
473
|
+
__decorateClass([
|
|
474
|
+
property({ type: Boolean })
|
|
475
|
+
], ObcCompassSector.prototype, "hasReadout", 2);
|
|
429
476
|
ObcCompassSector = __decorateClass([
|
|
430
477
|
customElement("obc-compass-sector")
|
|
431
478
|
], ObcCompassSector);
|