• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
17    var c = arguments.length,
18        r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21    return c > 3 && r && Object.defineProperty(target, key, r), r;
22};
23if (!("finalizeConstruction" in ViewPU.prototype)) {
24    Reflect.set(ViewPU.prototype, "finalizeConstruction", () => {
25    });
26}
27
28const animator = requireNapi('animator');
29const drawing = requireNapi('graphics.drawing');
30const vibrator = requireNapi('vibrator');
31const ColorMetrics = requireNapi('arkui.node').ColorMetrics;
32const hilog = requireNapi('hilog');
33const display = requireNapi('display');
34const PathShape = requireNapi('arkui.shape').PathShape;
35const systemDateTime = requireNapi('systemDateTime');
36
37const ANGLE_TO_RADIAN = Math.PI / 180; // Common or specific numerical values
38const RADIAN_TO_ANGLE = 180 / Math.PI;
39const PI_ANGLE = 180;
40const TWO_PI_RADIAN = 2 * Math.PI;
41const APPROXIMATE_NUMBER = Math.pow(10, -7);
42const ANGLE_OVER_MIN = 10 * ANGLE_TO_RADIAN;
43const LENGTH_OVER_MIN = 0.15;
44const INVALID_TIMEOUT_ID = -1;
45const RESTORE_TIMEOUT = 3000;
46const PROGRESS_DEFAULT = 0; // Default value
47const MIN_DEFAULT = 0;
48const MAX_DEFAULT = 100;
49const PADDING_DEFAULT = 5.5;
50const START_ANGLE_DEFAULT = 15;
51const END_ANGLE_DEFAULT = 45;
52const ACTIVE_START_ANGLE_DEFAULT = -60;
53const ACTIVE_END_ANGLE_DEFAULT = 60;
54const REVERSE_DEFAULT = true;
55const TRACK_THICKNESS_DEFAULT = 5;
56const ACTIVE_TRACK_THICKNESS_DEFAULT = 24;
57const TRACK_THICKNESS_MAX = 16;
58const ACTIVE_TRACK_THICKNESS_MAX = 36;
59const TRACK_BLUR_DEFAULT = 20;
60const TRACK_COLOR_DEFAULT = '#33FFFFFF';
61const SELECTED_COLOR_DEFAULT = '#FF5EA1FF';
62const BLUR_COLOR_DEFAULT = $r('sys.color.ohos_id_color_subtab_bg');
63const TOUCH_ANIMATION_DURATION = 200;
64const LIMIT_RESTORE_ANIMATION_DURATION = 333;
65const RESTORE_ANIMATION_DURATION = 167;
66const DIAMETER_DEFAULT = 233;
67const VIBRATOR_TYPE_TWO = 'watchhaptic.feedback.crown.strength2'; // About crown
68const CROWN_TIME_FLAG = 30;
69const CROWN_CONTROL_RATIO = 2.10;
70const CROWN_SENSITIVITY_LOW = 0.5;
71const CROWN_SENSITIVITY_MEDIUM = 1;
72const CROWN_SENSITIVITY_HIGH = 2;
73
74export var AnimatorStatus;
75(function (AnimatorStatus) {
76    AnimatorStatus[AnimatorStatus["MIN"] = 0] = "MIN";
77    AnimatorStatus[AnimatorStatus["MAX"] = 1] = "MAX";
78    AnimatorStatus[AnimatorStatus["NORMAL"] = 2] = "NORMAL";
79})(AnimatorStatus || (AnimatorStatus = {}));
80
81export var ClipPathArc;
82(function (ClipPathArc) {
83    ClipPathArc[ClipPathArc["ARC1"] = 0] = "ARC1";
84    ClipPathArc[ClipPathArc["ARC2"] = 1] = "ARC2";
85    ClipPathArc[ClipPathArc["ARC3"] = 2] = "ARC3";
86    ClipPathArc[ClipPathArc["ARC4"] = 3] = "ARC4";
87})(ClipPathArc || (ClipPathArc = {}));
88
89export var ArcSliderPosition;
90(function (ArcSliderPosition) {
91    ArcSliderPosition[ArcSliderPosition["LEFT"] = 0] = "LEFT";
92    ArcSliderPosition[ArcSliderPosition["RIGHT"] = 1] = "RIGHT";
93})(ArcSliderPosition || (ArcSliderPosition = {}));
94let ArcSliderValueOptions = class ArcSliderValueOptions {
95    constructor(options) {
96        this.progress = options?.progress ?? PROGRESS_DEFAULT;
97        this.min = options?.min ?? MIN_DEFAULT;
98        this.max = options?.max ?? MAX_DEFAULT;
99    }
100};
101__decorate([
102    Trace
103], ArcSliderValueOptions.prototype, "progress", void 0);
104__decorate([
105    Trace
106], ArcSliderValueOptions.prototype, "min", void 0);
107__decorate([
108    Trace
109], ArcSliderValueOptions.prototype, "max", void 0);
110ArcSliderValueOptions = __decorate([
111    ObservedV2
112], ArcSliderValueOptions);
113
114export { ArcSliderValueOptions };
115let ArcSliderLayoutOptions = class ArcSliderLayoutOptions {
116    constructor(options) {
117        this.reverse = options?.reverse ?? REVERSE_DEFAULT;
118        this.position = options?.position ?? ArcSliderPosition.RIGHT;
119    }
120};
121__decorate([
122    Trace
123], ArcSliderLayoutOptions.prototype, "reverse", void 0);
124__decorate([
125    Trace
126], ArcSliderLayoutOptions.prototype, "position", void 0);
127ArcSliderLayoutOptions = __decorate([
128    ObservedV2
129], ArcSliderLayoutOptions);
130
131export { ArcSliderLayoutOptions };
132let ArcSliderStyleOptions = class ArcSliderStyleOptions {
133    constructor(options) {
134        this.trackThickness = options?.trackThickness ?? TRACK_THICKNESS_DEFAULT;
135        this.activeTrackThickness = options?.activeTrackThickness ?? ACTIVE_TRACK_THICKNESS_DEFAULT;
136        this.trackColor = options?.trackColor ?? TRACK_COLOR_DEFAULT;
137        this.selectedColor = options?.selectedColor ?? SELECTED_COLOR_DEFAULT;
138        this.trackBlur = options?.trackBlur ?? TRACK_BLUR_DEFAULT;
139    }
140};
141__decorate([
142    Trace
143], ArcSliderStyleOptions.prototype, "trackThickness", void 0);
144__decorate([
145    Trace
146], ArcSliderStyleOptions.prototype, "activeTrackThickness", void 0);
147__decorate([
148    Trace
149], ArcSliderStyleOptions.prototype, "trackColor", void 0);
150__decorate([
151    Trace
152], ArcSliderStyleOptions.prototype, "selectedColor", void 0);
153__decorate([
154    Trace
155], ArcSliderStyleOptions.prototype, "trackBlur", void 0);
156ArcSliderStyleOptions = __decorate([
157    ObservedV2
158], ArcSliderStyleOptions);
159
160export { ArcSliderStyleOptions };
161let ArcSliderOptions = class ArcSliderOptions {
162    constructor(options) {
163        this.valueOptions = options?.valueOptions ?? new ArcSliderValueOptions();
164        this.layoutOptions = options?.layoutOptions ?? new ArcSliderLayoutOptions();
165        this.styleOptions = options?.styleOptions ?? new ArcSliderStyleOptions();
166        this.digitalCrownSensitivity = options?.digitalCrownSensitivity ?? CrownSensitivity.MEDIUM;
167        this.onTouch = options?.onTouch ?? ((event) => {
168        });
169        this.onChange = options?.onChange ?? ((progress) => {
170        });
171        this.onEnlarge = options?.onEnlarge ?? ((isEnlarged) => {
172        });
173    }
174};
175__decorate([
176    Trace
177], ArcSliderOptions.prototype, "valueOptions", void 0);
178__decorate([
179    Trace
180], ArcSliderOptions.prototype, "layoutOptions", void 0);
181__decorate([
182    Trace
183], ArcSliderOptions.prototype, "styleOptions", void 0);
184__decorate([
185    Trace
186], ArcSliderOptions.prototype, "digitalCrownSensitivity", void 0);
187__decorate([
188    Trace
189], ArcSliderOptions.prototype, "onTouch", void 0);
190__decorate([
191    Trace
192], ArcSliderOptions.prototype, "onChange", void 0);
193__decorate([
194    Trace
195], ArcSliderOptions.prototype, "onEnlarge", void 0);
196ArcSliderOptions = __decorate([
197    ObservedV2
198], ArcSliderOptions);
199
200export { ArcSliderOptions };
201
202export class DrawParameters {
203    constructor() {
204        this.lineWidth = 0;
205        this.radius = 0;
206        this.trackEndAngle = 0;
207        this.trackStartAngle = 0;
208        this.selectedStartAngle = 0;
209        this.selectedEndAngle = 0;
210        this.trackColor = ColorMetrics.resourceColor(TRACK_COLOR_DEFAULT);
211        this.selectedColor = ColorMetrics.resourceColor(SELECTED_COLOR_DEFAULT);
212        this.x = 0;
213        this.y = 0;
214        this.blur = TRACK_BLUR_DEFAULT;
215        this.uiContext = undefined;
216    }
217}
218
219export function nearEqual(num1, num2) {
220    return Math.abs(num1 - num2) < APPROXIMATE_NUMBER;
221}
222
223export class MyFullDrawModifier extends DrawModifier {
224    constructor(parameters) {
225        super();
226        this.parameters = new DrawParameters();
227        this.parameters = parameters;
228    }
229
230    parseColorString(color) {
231        return { alpha: color.alpha, red: color.red, green: color.green, blue: color.blue };
232    }
233
234    drawTrack(context) {
235        if (this.parameters.uiContext === undefined) {
236            hilog.error(0x3900, 'ArcSlider', `uiContext is undefined`);
237            return;
238        }
239        const canvas = context.canvas;
240        const pen = new drawing.Pen();
241        pen.setAntiAlias(true);
242        pen.setColor(this.parseColorString(this.parameters.trackColor));
243        pen.setStrokeWidth(this.parameters.uiContext.vp2px(this.parameters.lineWidth));
244        pen.setCapStyle(drawing.CapStyle.ROUND_CAP);
245        canvas.attachPen(pen);
246        const path = new drawing.Path();
247        const leftTopX = this.parameters.uiContext.vp2px(this.parameters.x - this.parameters.radius);
248        const leftTopY = this.parameters.uiContext.vp2px(this.parameters.y - this.parameters.radius);
249        const rightBottomX = this.parameters.uiContext.vp2px(this.parameters.x + this.parameters.radius);
250        const rightBottomY = this.parameters.uiContext.vp2px(this.parameters.y + this.parameters.radius);
251        let startAngle;
252        let sweepAngle;
253        startAngle = this.parameters.trackEndAngle * RADIAN_TO_ANGLE;
254        sweepAngle = (this.parameters.trackStartAngle - this.parameters.trackEndAngle) * RADIAN_TO_ANGLE;
255        path.arcTo(leftTopX, leftTopY, rightBottomX, rightBottomY, startAngle, sweepAngle);
256        canvas.drawPath(path);
257        canvas.detachPen();
258    }
259
260    drawSelection(context) {
261        if (this.parameters.uiContext === undefined) {
262            hilog.error(0x3900, 'ArcSlider', `uiContext is undefined`);
263            return;
264        }
265        if (nearEqual(this.parameters.selectedStartAngle, this.parameters.selectedEndAngle)) {
266            return;
267        }
268        const canvas = context.canvas;
269        const pen = new drawing.Pen();
270        pen.setAntiAlias(true);
271        pen.setColor(this.parseColorString(this.parameters.selectedColor));
272        pen.setStrokeWidth(this.parameters.uiContext.vp2px(this.parameters.lineWidth));
273        pen.setCapStyle(drawing.CapStyle.ROUND_CAP);
274        canvas.attachPen(pen);
275        let path = new drawing.Path();
276        const leftTopX = this.parameters.uiContext.vp2px(this.parameters.x - this.parameters.radius);
277        const leftTopY = this.parameters.uiContext.vp2px(this.parameters.y - this.parameters.radius);
278        const rightBottomX = this.parameters.uiContext.vp2px(this.parameters.x + this.parameters.radius);
279        const rightBottomY = this.parameters.uiContext.vp2px(this.parameters.y + this.parameters.radius);
280        let startAngle;
281        let sweepAngle;
282        startAngle = this.parameters.selectedEndAngle * RADIAN_TO_ANGLE;
283        sweepAngle = (this.parameters.selectedStartAngle - this.parameters.selectedEndAngle) * RADIAN_TO_ANGLE;
284        path.arcTo(leftTopX, leftTopY, rightBottomX, rightBottomY, startAngle, sweepAngle);
285        canvas.drawPath(path);
286        canvas.detachPen();
287    }
288
289    drawContent(context) {
290        this.drawTrack(context);
291    }
292
293    drawFront(context) {
294        this.drawSelection(context);
295    }
296}
297
298export class ArcSlider extends ViewV2 {
299    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
300        super(parent, elmtId, extraInfo);
301        this.initParam("options", (params && "options" in params) ? params.options : new ArcSliderOptions());
302        this.lineWidth = 0;
303        this.radius = 0;
304        this.trackStartAngle = 0;
305        this.trackEndAngle = 0;
306        this.selectedStartAngle = 0;
307        this.selectedEndAngle = 0;
308        this.selectRatioNow = 0;
309        this.isEnlarged = false;
310        this.clipPath = '';
311        this.isReverse = false;
312        this.isLargeArc = false;
313        this.isFocus = false;
314        this.timePre = "timePre" in params ? params.timePre : 0;
315        this.timeCur = "timeCur" in params ? params.timeCur : 0;
316        this.parameters = "parameters" in params ? params.parameters : new DrawParameters();
317        this.fullModifier = "fullModifier" in params ? params.fullModifier : new MyFullDrawModifier(this.parameters);
318        this.touchAnimator = "touchAnimator" in params ? params.touchAnimator : undefined;
319        this.restoreAnimator = "restoreAnimator" in params ? params.restoreAnimator : undefined;
320        this.maxRestoreAnimator = "maxRestoreAnimator" in params ? params.maxRestoreAnimator : undefined;
321        this.minRestoreAnimator = "minRestoreAnimator" in params ? params.minRestoreAnimator : undefined;
322        this.delta = "delta" in params ? params.delta : 0;
323        this.crownDeltaAngle = "crownDeltaAngle" in params ? params.crownDeltaAngle : 0;
324        this.lineWidthBegin = "lineWidthBegin" in params ? params.lineWidthBegin : 0;
325        this.touchY = "touchY" in params ? params.touchY : 0;
326        this.meter = "meter" in params ? params.meter : 0;
327        this.trackStartAngleBegin = "trackStartAngleBegin" in params ? params.trackStartAngleBegin : 0;
328        this.selectedEndAngleBegin = "selectedEndAngleBegin" in params ? params.selectedEndAngleBegin : 0;
329        this.isTouchAnimatorFinished = "isTouchAnimatorFinished" in params ? params.isTouchAnimatorFinished : false;
330        this.clickValue = "clickValue" in params ? params.clickValue : 0;
331        this.normalStartAngle = "normalStartAngle" in params ? params.normalStartAngle : 0;
332        this.normalEndAngle = "normalEndAngle" in params ? params.normalEndAngle : 0;
333        this.activeStartAngle = "activeStartAngle" in params ? params.activeStartAngle : 0;
334        this.activeEndAngle = "activeEndAngle" in params ? params.activeEndAngle : 0;
335        this.selectedMaxOrMin = "selectedMaxOrMin" in params ? params.selectedMaxOrMin : AnimatorStatus.NORMAL;
336        this.needVibrate = "needVibrate" in params ? params.needVibrate : true;
337        this.crownEventCounter = "crownEventCounter" in params ? params.crownEventCounter : 0;
338        this.diameter = "diameter" in params ? params.diameter : 0;
339        this.isAntiClock = "isAntiClock" in params ? params.isAntiClock : true;
340        this.normalRadius = "normalRadius" in params ? params.normalRadius : 0;
341        this.finalizeConstruction();
342    }
343
344    onChange(monitor) {
345        monitor.dirty.forEach((path) => {
346            const isAntiClockChanged = monitor.value('isAntiClock')?.now !== monitor.value('isAntiClock')?.before;
347            const isReverseChanged = monitor.value('options.layoutOptions.reverse')?.now !==
348                monitor.value('options.layoutOptions.reverse')?.before;
349            const isThicknessChanged = monitor.value('options.styleOptions.activeTrackThickness')?.now !==
350                monitor.value('options.styleOptions.activeTrackThickness')?.before;
351            if (isAntiClockChanged || isReverseChanged) {
352                this.selectedStartAngle = this.activeStartAngle;
353                this.trackEndAngle = this.activeEndAngle;
354                this.trackStartAngle = this.activeStartAngle;
355            }
356            if (isThicknessChanged) {
357                this.lineWidth = this.options.styleOptions.activeTrackThickness;
358            }
359            this.updateArcSlider();
360        });
361    }
362
363    aboutToAppear() {
364        this.updateArcSlider();
365        this.resetDrawing();
366        this.setTouchAnimator();
367        this.setMaxRestoreAnimator();
368        this.setMinRestoreAnimator();
369        this.setRestoreAnimator();
370        this.setDiameter();
371    }
372
373    aboutToDisappear() {
374        clearTimeout(this.meter);
375        this.touchAnimator = undefined;
376        this.restoreAnimator = undefined;
377        this.maxRestoreAnimator = undefined;
378        this.minRestoreAnimator = undefined;
379    }
380
381    setTouchAnimator() {
382        this.touchAnimator = animator.create({
383            duration: TOUCH_ANIMATION_DURATION,
384            easing: 'friction',
385            delay: 0,
386            fill: 'forwards',
387            direction: 'normal',
388            iterations: 1,
389            begin: 0,
390            end: 1
391        });
392        this.touchAnimator.onFrame = (fraction) => {
393            this.lineWidth = this.calcAnimatorChange(this.options.styleOptions.trackThickness, this.options.styleOptions.activeTrackThickness, fraction);
394            this.selectedStartAngle = this.calcAnimatorChange(this.normalStartAngle, this.activeStartAngle, fraction);
395            this.trackStartAngle = this.selectedStartAngle;
396            this.trackEndAngle = this.calcAnimatorChange(this.normalEndAngle, this.activeEndAngle, fraction);
397            this.resetDrawing();
398        };
399        this.touchAnimator.onFinish = () => {
400            this.isTouchAnimatorFinished = true;
401        };
402    }
403
404    startTouchAnimator() {
405        if (this.touchAnimator) {
406            this.options.onEnlarge?.(true);
407            this.touchAnimator.play();
408        }
409    }
410
411    setMaxRestoreAnimator() {
412        this.maxRestoreAnimator = animator.create({
413            duration: LIMIT_RESTORE_ANIMATION_DURATION,
414            easing: 'sharp',
415            delay: 0,
416            fill: 'forwards',
417            direction: 'normal',
418            iterations: 1,
419            begin: 0,
420            end: 1
421        });
422        this.maxRestoreAnimator.onFrame = (fraction) => {
423            this.lineWidth = this.calcAnimatorChange(this.lineWidthBegin, this.options.styleOptions.activeTrackThickness, fraction);
424            this.selectedEndAngle = this.calcAnimatorChange(this.selectedEndAngleBegin, this.activeEndAngle, fraction);
425            this.trackEndAngle = this.selectedEndAngle;
426            this.resetDrawing();
427        };
428        this.maxRestoreAnimator.onFinish = () => {
429            this.selectedMaxOrMin = AnimatorStatus.NORMAL;
430        };
431    }
432
433    startMaxRestoreAnimator() {
434        if (this.maxRestoreAnimator) {
435            this.maxRestoreAnimator.play();
436        }
437    }
438
439    setMinRestoreAnimator() {
440        this.minRestoreAnimator = animator.create({
441            duration: LIMIT_RESTORE_ANIMATION_DURATION,
442            easing: 'sharp',
443            delay: 0,
444            fill: 'forwards',
445            direction: 'normal',
446            iterations: 1,
447            begin: 0,
448            end: 1
449        });
450        this.minRestoreAnimator.onFrame = (fraction) => {
451            this.lineWidth = this.calcAnimatorChange(this.lineWidthBegin, this.options.styleOptions.activeTrackThickness, fraction);
452            this.trackStartAngle = this.calcAnimatorChange(this.trackStartAngleBegin, this.activeStartAngle, fraction);
453            this.resetDrawing();
454        };
455        this.minRestoreAnimator.onFinish = () => {
456            this.selectedMaxOrMin = AnimatorStatus.NORMAL;
457        };
458    }
459
460    startMinRestoreAnimator() {
461        if (this.minRestoreAnimator) {
462            this.minRestoreAnimator.play();
463        }
464    }
465
466    setRestoreAnimator() {
467        this.restoreAnimator = animator.create({
468            duration: RESTORE_ANIMATION_DURATION,
469            easing: 'friction',
470            delay: 0,
471            fill: 'forwards',
472            direction: 'normal',
473            iterations: 1,
474            begin: 0,
475            end: 1
476        });
477        this.restoreAnimator.onFrame = (fraction) => {
478            this.lineWidth = this.calcAnimatorChange(this.options.styleOptions.activeTrackThickness, this.options.styleOptions.trackThickness, fraction);
479            this.selectedStartAngle = this.calcAnimatorChange(this.activeStartAngle, this.normalStartAngle, fraction) *
480                ANGLE_TO_RADIAN;
481            this.trackStartAngle = this.selectedStartAngle;
482            this.trackEndAngle = this.calcAnimatorChange(this.activeEndAngle, this.normalEndAngle, fraction) *
483                ANGLE_TO_RADIAN;
484            this.resetDrawing();
485        };
486    }
487
488    startRestoreAnimator() {
489        if (this.restoreAnimator) {
490            this.options.onEnlarge?.(false);
491            this.restoreAnimator.play();
492        }
493    }
494
495    updateArcSlider() {
496        this.checkParam();
497        this.setLayoutState(this.options.layoutOptions.reverse, this.options.layoutOptions.position);
498        this.resetDrawing();
499    }
500
501    setLimitValues(attr, defaultValue, min, max) {
502        if (attr < min) {
503            attr = defaultValue;
504        }
505        if (max != undefined && attr > max) {
506            attr = defaultValue;
507        }
508        return attr;
509    }
510
511    checkParam() {
512        if (this.options.valueOptions.max === this.options.valueOptions.min ||
513            this.options.valueOptions.max < this.options.valueOptions.min) {
514            this.options.valueOptions.max = MAX_DEFAULT;
515            this.options.valueOptions.min = MIN_DEFAULT;
516            this.options.valueOptions.progress = PROGRESS_DEFAULT;
517        }
518        this.options.valueOptions.progress = Math.min(this.options.valueOptions.max, this.options.valueOptions.progress);
519        this.options.valueOptions.progress = Math.max(this.options.valueOptions.min, this.options.valueOptions.progress);
520        this.options.styleOptions.trackBlur = this.setLimitValues(this.options.styleOptions.trackBlur, TRACK_BLUR_DEFAULT, 0);
521        this.options.styleOptions.trackThickness = this.setLimitValues(this.options.styleOptions.trackThickness, TRACK_THICKNESS_DEFAULT, TRACK_THICKNESS_DEFAULT, TRACK_THICKNESS_MAX);
522        this.options.styleOptions.activeTrackThickness = this.setLimitValues(this.options.styleOptions.activeTrackThickness, ACTIVE_TRACK_THICKNESS_DEFAULT, ACTIVE_TRACK_THICKNESS_DEFAULT, ACTIVE_TRACK_THICKNESS_MAX);
523    }
524
525    updateModifier() {
526        this.parameters.lineWidth = this.lineWidth;
527        this.parameters.radius = this.radius;
528        this.parameters.selectedStartAngle = this.selectedStartAngle;
529        this.parameters.trackEndAngle = this.trackEndAngle;
530        this.parameters.trackStartAngle = this.trackStartAngle;
531        this.parameters.selectedEndAngle = this.selectedEndAngle;
532        try {
533            this.parameters.trackColor = ColorMetrics.resourceColor(this.options.styleOptions.trackColor);
534        }
535        catch (err) {
536            let error = err;
537            console.error(`Failed to set track color, code = ${error.code}, message =${error.message}`);
538            this.parameters.trackColor = ColorMetrics.resourceColor(TRACK_COLOR_DEFAULT);
539        }
540        try {
541            this.parameters.selectedColor = ColorMetrics.resourceColor(this.options.styleOptions.selectedColor);
542        }
543        catch (err) {
544            let error = err;
545            console.error(`Failed to set selected color, code = ${error.code}, message =${error.message}`);
546            this.parameters.selectedColor = ColorMetrics.resourceColor(SELECTED_COLOR_DEFAULT);
547        }
548        this.parameters.blur = this.options.styleOptions.trackBlur;
549    }
550
551    setDiameter() {
552        let width;
553        try {
554            width = display.getDefaultDisplaySync().width;
555        }
556        catch (err) {
557            let error = err;
558            console.error(`Failed to get default display width, code = ${error.code}, message =${error.message}`);
559            width = 0;
560        }
561        this.parameters.uiContext = this.getUIContext();
562        if (this.parameters.uiContext) {
563            if (width !== 0) {
564                this.diameter = this.parameters.uiContext.px2vp(width);
565            }
566            else {
567                this.diameter = DIAMETER_DEFAULT;
568            }
569        }
570        this.normalRadius = this.diameter / 2;
571        this.parameters.x = this.normalRadius;
572        this.parameters.y = this.normalRadius;
573    }
574
575    resetDrawing() {
576        this.setLayoutOptions();
577        this.updateModifier();
578        this.fullModifier.invalidate();
579        this.calcBlur();
580    }
581
582    setLayoutState(reverse, position) {
583        const normalStartAngleRight = -START_ANGLE_DEFAULT * ANGLE_TO_RADIAN;
584        const normalEndAngleRight = -END_ANGLE_DEFAULT * ANGLE_TO_RADIAN;
585        const activeStartAngleRight = -ACTIVE_START_ANGLE_DEFAULT * ANGLE_TO_RADIAN;
586        const activeEndAngleRight = -ACTIVE_END_ANGLE_DEFAULT * ANGLE_TO_RADIAN;
587        const normalStartAngleLeft = -Math.PI - normalStartAngleRight;
588        const normalEndAngleLeft = -Math.PI - normalEndAngleRight;
589        const activeStartAngleLeft = -Math.PI - activeStartAngleRight;
590        const activeEndAngleLeft = -Math.PI - activeEndAngleRight;
591        if (reverse && position === ArcSliderPosition.RIGHT) {
592            this.isAntiClock = true;
593            this.normalStartAngle = normalStartAngleRight;
594            this.normalEndAngle = normalEndAngleRight;
595            this.activeStartAngle = activeStartAngleRight;
596            this.activeEndAngle = activeEndAngleRight;
597        }
598        else if (!reverse && position === ArcSliderPosition.RIGHT) {
599            this.isAntiClock = false;
600            this.normalStartAngle = normalEndAngleRight;
601            this.normalEndAngle = normalStartAngleRight;
602            this.activeStartAngle = activeEndAngleRight;
603            this.activeEndAngle = activeStartAngleRight;
604        }
605        else if (reverse && position === ArcSliderPosition.LEFT) {
606            this.isAntiClock = false;
607            this.normalStartAngle = normalStartAngleLeft;
608            this.normalEndAngle = normalEndAngleLeft;
609            this.activeStartAngle = activeStartAngleLeft;
610            this.activeEndAngle = activeEndAngleLeft;
611        }
612        else if (!reverse && position === ArcSliderPosition.LEFT) {
613            this.isAntiClock = true;
614            this.normalStartAngle = normalEndAngleLeft;
615            this.normalEndAngle = normalStartAngleLeft;
616            this.activeStartAngle = activeEndAngleLeft;
617            this.activeEndAngle = activeStartAngleLeft;
618        }
619    }
620
621    setLayoutOptions() {
622        this.radius = this.normalRadius - (this.lineWidth / 2);
623        // Without setting the angle and width in the enlarged state, the animation will be affected
624        if (!this.isEnlarged) {
625            this.selectedStartAngle = this.normalStartAngle;
626            this.trackEndAngle = this.normalEndAngle;
627            this.trackStartAngle = this.normalStartAngle;
628            this.radius = this.radius - PADDING_DEFAULT;
629            this.lineWidth = this.options.styleOptions.trackThickness;
630        }
631        const selectedRatio = (this.options.valueOptions.progress - this.options.valueOptions.min) /
632            (this.options.valueOptions.max - this.options.valueOptions.min);
633        const deltaRadian = this.trackEndAngle - this.selectedStartAngle;
634        const selectedAngle = selectedRatio * Math.abs(deltaRadian);
635        if (this.trackEndAngle > this.selectedStartAngle) {
636            this.selectedEndAngle = this.selectedStartAngle + selectedAngle;
637        }
638        else {
639            this.selectedEndAngle = this.selectedStartAngle - selectedAngle;
640        }
641        this.calcBlur();
642    }
643
644    calcPathXY(isRLarge) {
645        if (this.parameters.uiContext) {
646            const halfLineWidth = this.parameters.lineWidth / 2;
647            let distance = this.parameters.radius;
648            let angle = 0;
649            if (isRLarge === ClipPathArc.ARC1) {
650                distance += halfLineWidth;
651                angle = this.parameters.trackStartAngle;
652            }
653            else if (isRLarge === ClipPathArc.ARC2) {
654                distance += halfLineWidth;
655                angle = this.parameters.trackEndAngle;
656            }
657            else if (isRLarge === ClipPathArc.ARC3) {
658                distance -= halfLineWidth;
659                angle = this.parameters.trackEndAngle;
660            }
661            else if (isRLarge === ClipPathArc.ARC4) {
662                distance -= halfLineWidth;
663                angle = this.parameters.trackStartAngle;
664            }
665            return `${(this.parameters.uiContext.vp2px(this.parameters.x + distance * Math.cos(angle)))} ` +
666                `${(this.parameters.uiContext.vp2px(this.parameters.y + (distance) * Math.sin(angle)))}`;
667        }
668        return 0;
669    }
670
671    calcPathR(isRLarge) {
672        if (this.parameters.uiContext) {
673            const halfLineWidth = this.parameters.lineWidth / 2;
674            let pathR = this.parameters.uiContext.vp2px(halfLineWidth);
675            if (isRLarge === ClipPathArc.ARC2) {
676                pathR += this.parameters.uiContext.vp2px(this.parameters.radius);
677            }
678            else if (isRLarge === ClipPathArc.ARC4) {
679                pathR = this.parameters.uiContext.vp2px(this.parameters.radius) - pathR;
680            }
681            return `${pathR} ${pathR}`;
682        }
683        return 0;
684    }
685
686    setClipPath() {
687        let littleArc = this.calcPathR(ClipPathArc.ARC1);
688        const sourcePoint = `M${this.calcPathXY(ClipPathArc.ARC4)}`;
689        const arc1 = ` A${littleArc} 0 1 ` + `${Number(this.isReverse)} ${this.calcPathXY(ClipPathArc.ARC1)}`;
690        const arc2 = ` A${this.calcPathR(ClipPathArc.ARC2)} 0 ${Number(this.isLargeArc)} ${Number(this.isReverse)} ` +
691            `${this.calcPathXY(ClipPathArc.ARC2)}`;
692        const arc3 = ` A${littleArc} 0 1 ` + `${Number(this.isReverse)} ${this.calcPathXY(ClipPathArc.ARC3)}`;
693        const arc4 = ` A${this.calcPathR(ClipPathArc.ARC4)} 0 ${Number(this.isLargeArc)} ${Number(!this.isReverse)} ` +
694            `${this.calcPathXY(ClipPathArc.ARC4)}`;
695        this.clipPath = sourcePoint + arc1 + arc2 + arc3 + arc4;
696    }
697
698    calcBlur() {
699        this.isLargeArc = false;
700        if (this.isAntiClock) {
701            this.isReverse = false;
702        }
703        else {
704            this.isReverse = true;
705        }
706        this.setClipPath();
707    }
708
709    calcAnimatorChange(start, end, fraction) {
710        return (fraction * (end - start) + start);
711    }
712
713    calcClickValue(clickX, clickY) {
714        if (clickY - this.normalRadius > this.radius) {
715            clickY = this.radius + this.normalRadius;
716        }
717        else if (this.normalRadius - clickY > this.radius) {
718            clickY = this.normalRadius - this.radius;
719        }
720        const sin = Math.abs(clickY - this.normalRadius) / this.radius;
721        let radian = Math.asin(sin);
722        const isXPositive = clickX > this.normalRadius;
723        const isYPositive = clickY > this.normalRadius;
724        if (!isXPositive && isYPositive) {
725            radian = -Math.PI - radian;
726        }
727        else if (!isXPositive && !isYPositive) {
728            radian = radian - Math.PI;
729        }
730        else if (isXPositive && !isYPositive) {
731            radian = -radian;
732        }
733        this.selectedEndAngle = radian;
734        const delta = (this.selectedStartAngle - this.selectedEndAngle) / ANGLE_TO_RADIAN;
735        if (!this.isAntiClock) {
736            this.selectRatioNow = -delta / (ACTIVE_END_ANGLE_DEFAULT - ACTIVE_START_ANGLE_DEFAULT);
737        }
738        else {
739            this.selectRatioNow = delta / (ACTIVE_END_ANGLE_DEFAULT - ACTIVE_START_ANGLE_DEFAULT);
740        }
741        this.selectRatioNow = Math.min(1, this.selectRatioNow);
742        this.selectRatioNow = Math.max(0, this.selectRatioNow);
743        this.clickValue = this.selectRatioNow * (this.options.valueOptions.max - this.options.valueOptions.min) +
744        this.options.valueOptions.min;
745        this.options.valueOptions.progress = this.clickValue;
746        this.setLayoutOptions();
747        this.updateModifier();
748        this.fullModifier.invalidate();
749    }
750
751    calcValue(moveY) {
752        this.delta = this.touchY - moveY;
753        const total = this.radius * Math.sqrt(3);
754        let valueNow = (this.options.valueOptions.progress - this.options.valueOptions.min) /
755            (this.options.valueOptions.max - this.options.valueOptions.min);
756        if (this.options.layoutOptions.reverse) {
757            valueNow += this.delta / total;
758        }
759        else {
760            valueNow -= this.delta / total;
761        }
762        valueNow = Math.min(1, valueNow);
763        valueNow = Math.max(0, valueNow);
764        this.options.valueOptions.progress = valueNow * (this.options.valueOptions.max - this.options.valueOptions.min) +
765        this.options.valueOptions.min;
766        this.setLayoutOptions();
767        this.updateModifier();
768        this.fullModifier.invalidate();
769        this.touchY = moveY;
770    }
771
772    calcCrownTotal(activeStartAngle, activeEndAngle) {
773        if (activeEndAngle > activeStartAngle) {
774            if (this.options.layoutOptions.reverse) {
775                return (TWO_PI_RADIAN - Math.abs(activeEndAngle - activeStartAngle));
776            }
777            return Math.abs(activeEndAngle - activeStartAngle);
778        }
779        else {
780            if (this.options.layoutOptions.reverse) {
781                return Math.abs(activeEndAngle - activeStartAngle);
782            }
783            return (TWO_PI_RADIAN - Math.abs(activeEndAngle - activeStartAngle));
784        }
785    }
786
787    calcCrownValue(deltaCrownAngle) {
788        const totalAngle = this.calcCrownTotal(this.activeStartAngle, this.activeEndAngle);
789        const totalValue = this.options.valueOptions.max - this.options.valueOptions.min;
790        let valueNow = (this.options.valueOptions.progress - this.options.valueOptions.min) / totalValue;
791        valueNow += deltaCrownAngle / totalAngle;
792        valueNow = Math.min(1, valueNow);
793        valueNow = Math.max(0, valueNow);
794        this.options.valueOptions.progress = valueNow * totalValue + this.options.valueOptions.min;
795        this.setLayoutOptions();
796        this.updateModifier();
797        this.fullModifier.invalidate();
798    }
799
800    calcMaxValueDeltaIsPositive(delta) {
801        const isLineWidthFitted = this.lineWidth >= this.options.styleOptions.activeTrackThickness *
802            (1 - LENGTH_OVER_MIN);
803        if (this.isAntiClock) {
804            const isEndAngleFitted = this.selectedEndAngle >= (this.activeEndAngle - ANGLE_OVER_MIN);
805            if (isEndAngleFitted && isLineWidthFitted) {
806                this.selectedEndAngle -= (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius + Math.abs(this.delta));
807                this.lineWidth -= LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) / (LENGTH_OVER_MIN * this.lineWidth +
808                Math.abs(this.delta));
809                this.trackEndAngle = this.selectedEndAngle;
810            }
811            if (this.selectedEndAngle <= (this.activeEndAngle - ANGLE_OVER_MIN)) {
812                this.selectedEndAngle = this.activeEndAngle - ANGLE_OVER_MIN;
813            }
814        }
815        else {
816            const isEndAngleFitted = this.selectedEndAngle <= (this.activeEndAngle + ANGLE_OVER_MIN);
817            if (isEndAngleFitted && isLineWidthFitted) {
818                this.selectedEndAngle += (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius + Math.abs(this.delta));
819                this.lineWidth -= LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) / (LENGTH_OVER_MIN * this.lineWidth +
820                Math.abs(this.delta));
821                this.trackEndAngle = this.selectedEndAngle;
822            }
823            if (this.selectedEndAngle >= (this.activeEndAngle + ANGLE_OVER_MIN)) {
824                this.selectedEndAngle = this.activeEndAngle + ANGLE_OVER_MIN;
825            }
826        }
827        this.trackEndAngle = this.selectedEndAngle;
828        if (this.lineWidth <= this.options.styleOptions.activeTrackThickness * (1 - LENGTH_OVER_MIN)) {
829            this.lineWidth = this.options.styleOptions.activeTrackThickness * (1 - LENGTH_OVER_MIN);
830        }
831    }
832
833    calcMaxValueDeltaIsNegative(delta) {
834        const isLineWidthFitted = this.lineWidth <= this.options.styleOptions.activeTrackThickness;
835        const isEndAngleFitted = this.selectedEndAngle <= this.activeEndAngle;
836        if (this.isAntiClock) {
837            if (isEndAngleFitted || isLineWidthFitted) {
838                this.selectedEndAngle -= (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius + Math.abs(this.delta));
839            }
840            if (this.selectedEndAngle >= this.activeEndAngle) {
841                this.selectedEndAngle = this.activeEndAngle;
842                this.trackEndAngle = this.selectedEndAngle;
843            }
844        }
845        else {
846            if ((!isEndAngleFitted) || isLineWidthFitted) {
847                this.selectedEndAngle += (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius + Math.abs(this.delta));
848            }
849            if (this.selectedEndAngle <= this.activeEndAngle) {
850                this.selectedEndAngle = this.activeEndAngle;
851                this.trackEndAngle = this.selectedEndAngle;
852            }
853        }
854        this.lineWidth += LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) / (LENGTH_OVER_MIN * this.lineWidth +
855        Math.abs(this.delta));
856        this.trackEndAngle = this.selectedEndAngle;
857        if (this.lineWidth >= this.options.styleOptions.activeTrackThickness) {
858            this.lineWidth = this.options.styleOptions.activeTrackThickness;
859        }
860    }
861
862    calcMaxValue(moveY) {
863        this.delta = this.touchY - moveY;
864        let delta = this.delta;
865        if (!this.options.layoutOptions.reverse) {
866            delta = -this.delta;
867        }
868        if (delta >= 0) {
869            this.calcMaxValueDeltaIsPositive(delta);
870        }
871        else {
872            this.calcMaxValueDeltaIsNegative(delta);
873        }
874        this.updateModifier();
875        this.fullModifier.invalidate();
876        this.touchY = moveY;
877        this.calcBlur();
878    }
879
880    calcMinValueDeltaIsNegative(delta) {
881        const isLineWidthFitted = this.lineWidth >= this.options.styleOptions.activeTrackThickness *
882            (1 - LENGTH_OVER_MIN);
883        if (this.isAntiClock) {
884            const isStartAngleFitted = this.trackStartAngle <= this.selectedStartAngle + ANGLE_OVER_MIN;
885            if (isStartAngleFitted && isLineWidthFitted) {
886                this.trackStartAngle -= (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius +
887                Math.abs(this.delta));
888                this.lineWidth -= LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) /
889                    (LENGTH_OVER_MIN * this.lineWidth + Math.abs(this.delta));
890            }
891            if (this.trackStartAngle >= this.selectedStartAngle + ANGLE_OVER_MIN) {
892                this.trackStartAngle = this.selectedStartAngle + ANGLE_OVER_MIN;
893            }
894        }
895        else {
896            const isStartAngleFitted = this.trackStartAngle >= this.selectedStartAngle - ANGLE_OVER_MIN;
897            if (isStartAngleFitted && isLineWidthFitted) {
898                this.trackStartAngle += (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius +
899                Math.abs(this.delta));
900                this.lineWidth -= LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) /
901                    (LENGTH_OVER_MIN * this.lineWidth + Math.abs(this.delta));
902            }
903            if (this.trackStartAngle <= this.selectedStartAngle - ANGLE_OVER_MIN) {
904                this.trackStartAngle = this.selectedStartAngle - ANGLE_OVER_MIN;
905            }
906        }
907        if (this.lineWidth <= this.options.styleOptions.activeTrackThickness * (1 - LENGTH_OVER_MIN)) {
908            this.lineWidth = this.options.styleOptions.activeTrackThickness * (1 - LENGTH_OVER_MIN);
909        }
910    }
911
912    calcMinValueDeltaIsPositive(delta) {
913        const isLineWidthFitted = this.lineWidth <= this.options.styleOptions.activeTrackThickness;
914        const isStartAngleFitted = this.trackStartAngle > this.selectedStartAngle;
915        if (this.isAntiClock) {
916            if (isStartAngleFitted || isLineWidthFitted) {
917                this.trackStartAngle -= (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius + Math.abs(this.delta));
918                this.lineWidth += LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) / (LENGTH_OVER_MIN * this.lineWidth +
919                Math.abs(this.delta));
920            }
921            if (this.trackStartAngle < this.selectedStartAngle) {
922                this.trackStartAngle = this.selectedStartAngle;
923            }
924        }
925        else {
926            if (!isStartAngleFitted || isLineWidthFitted) {
927                this.trackStartAngle += (ANGLE_OVER_MIN) * delta / (ANGLE_OVER_MIN * this.radius + Math.abs(this.delta));
928                this.lineWidth += LENGTH_OVER_MIN * this.lineWidth * Math.abs(this.delta) / (LENGTH_OVER_MIN * this.lineWidth +
929                Math.abs(this.delta));
930            }
931            if (this.trackStartAngle > this.selectedStartAngle) {
932                this.trackStartAngle = this.selectedStartAngle;
933            }
934        }
935        if (this.lineWidth >= this.options.styleOptions.activeTrackThickness) {
936            this.lineWidth = this.options.styleOptions.activeTrackThickness;
937        }
938    }
939
940    calcMinValue(moveY) {
941        this.delta = this.touchY - moveY;
942        let delta = this.delta;
943        if (!this.options.layoutOptions.reverse) {
944            delta = -this.delta;
945        }
946        if (delta <= 0) {
947            this.calcMinValueDeltaIsNegative(delta);
948        }
949        else {
950            this.calcMinValueDeltaIsPositive(delta);
951        }
952        this.updateModifier();
953        this.fullModifier.invalidate();
954        this.touchY = moveY;
955        this.calcBlur();
956    }
957
958    isHotRegion(touchX, touchY) {
959        const radius = Math.sqrt(Math.pow(touchX - this.normalRadius, 2) + Math.pow(touchY - this.normalRadius, 2));
960        let isRadiusNoFitted = (radius < this.normalRadius - this.options.styleOptions.activeTrackThickness) ||
961            (radius > this.normalRadius);
962        if (isRadiusNoFitted) {
963            return false;
964        }
965        const sin = Math.abs(touchY - this.normalRadius) / radius;
966        const radian = Math.asin(sin);
967        let angle = radian / ANGLE_TO_RADIAN;
968        const isXPositive = touchX > this.normalRadius;
969        const isYPositive = touchY > this.normalRadius;
970        if (!isXPositive && isYPositive) {
971            angle = -PI_ANGLE - angle;
972        }
973        else if (!isXPositive && !isYPositive) {
974            angle = angle - PI_ANGLE;
975        }
976        else if (isXPositive && !isYPositive) {
977            angle = -angle;
978        }
979        let angleToRadian = angle * ANGLE_TO_RADIAN;
980        const isAntiClockAngleFitted = angleToRadian <= this.selectedStartAngle &&
981            angleToRadian >= this.trackEndAngle;
982        const isClockAngleFitted = angleToRadian >= this.selectedStartAngle && angleToRadian <= this.trackEndAngle;
983        if (this.isAntiClock && isAntiClockAngleFitted || !this.isAntiClock && isClockAngleFitted) {
984            return true;
985        }
986        return false;
987    }
988
989    calcDisplayControlRatio(crownSensitivity) {
990        if (crownSensitivity === CrownSensitivity.LOW) {
991            return CROWN_CONTROL_RATIO * CROWN_SENSITIVITY_LOW;
992        }
993        else if (crownSensitivity === CrownSensitivity.MEDIUM) {
994            return CROWN_CONTROL_RATIO * CROWN_SENSITIVITY_MEDIUM;
995        }
996        else if (crownSensitivity === CrownSensitivity.HIGH) {
997            return CROWN_CONTROL_RATIO * CROWN_SENSITIVITY_HIGH;
998        }
999        return CROWN_CONTROL_RATIO * CROWN_SENSITIVITY_MEDIUM;
1000    }
1001
1002    clearTimeout() {
1003        if (this.meter !== INVALID_TIMEOUT_ID) {
1004            clearTimeout(this.meter);
1005            this.meter = INVALID_TIMEOUT_ID;
1006        }
1007    }
1008
1009    onTouchEvent(event) {
1010        const isTouchTypeUp = this.isEnlarged && event.type === TouchType.Up;
1011        const isTouchTypeMove = this.isEnlarged && this.isTouchAnimatorFinished && event.type === TouchType.Move;
1012        if (event.type === TouchType.Down) {
1013            this.isFocus = false;
1014            if (this.isHotRegion(event.touches[0].x, event.touches[0].y)) {
1015                this.isFocus = true;
1016            }
1017            this.onTouchDown(event);
1018        }
1019        else if (isTouchTypeUp) {
1020            this.clearTimeout();
1021            if (this.isHotRegion(event.touches[0].x, event.touches[0].y)) {
1022                this.options.onTouch?.(event);
1023            }
1024            this.meter = setTimeout(() => {
1025                if (this.isEnlarged) {
1026                    this.isTouchAnimatorFinished = false;
1027                    this.isEnlarged = false;
1028                    this.startRestoreAnimator();
1029                    this.calcBlur();
1030                }
1031            }, RESTORE_TIMEOUT);
1032            this.isMaxOrMinAnimator();
1033        }
1034        else if (isTouchTypeMove && this.isFocus) {
1035            this.options.onTouch?.(event);
1036            this.onTouchMove(event.touches[0].y);
1037            this.options.onChange?.(this.options.valueOptions.progress);
1038            this.clearTimeout();
1039        }
1040    }
1041
1042    onTouchDown(event) {
1043        if (!this.isEnlarged) {
1044            this.touchY = event.touches[0].y;
1045            this.clearTimeout();
1046            if (this.isHotRegion(event.touches[0].x, event.touches[0].y)) {
1047                this.options.onTouch?.(event);
1048                this.isEnlarged = true;
1049                this.startTouchAnimator();
1050                this.calcBlur();
1051            }
1052        }
1053        else {
1054            this.touchY = event.touches[0].y;
1055            if (this.isHotRegion(event.touches[0].x, event.touches[0].y)) {
1056                this.options.onTouch?.(event);
1057                this.clearTimeout();
1058                if (this.isTouchAnimatorFinished) {
1059                    this.calcClickValue(event.touches[0].x, event.touches[0].y);
1060                }
1061                this.touchY = event.touches[0].y;
1062                this.calcValue(event.touches[0].y);
1063                this.options.onChange?.(this.options.valueOptions.progress);
1064                this.setLayoutOptions();
1065                this.updateModifier();
1066                this.fullModifier.invalidate();
1067            }
1068        }
1069    }
1070
1071    isMaxOrMinAnimator() {
1072        let selectedEndAngle = this.selectedEndAngle;
1073        let trackStartAngle = this.trackStartAngle;
1074        let activeEndAngle = this.activeEndAngle;
1075        let activeStartAngle = this.activeStartAngle;
1076        if (!this.isAntiClock) {
1077            selectedEndAngle = -this.selectedEndAngle;
1078            trackStartAngle = -this.trackStartAngle;
1079            activeEndAngle = -this.activeEndAngle;
1080            activeStartAngle = -this.activeStartAngle;
1081        }
1082        const canMaxRestoreAnimatorStart = this.selectedMaxOrMin === AnimatorStatus.MAX &&
1083            selectedEndAngle < activeEndAngle;
1084        const canMinRestoreAnimatorStart = this.selectedMaxOrMin === AnimatorStatus.MIN &&
1085            trackStartAngle > activeStartAngle;
1086        if (canMaxRestoreAnimatorStart) {
1087            this.lineWidthBegin = this.lineWidth;
1088            this.selectedEndAngleBegin = this.selectedEndAngle;
1089            this.startMaxRestoreAnimator();
1090        }
1091        if (canMinRestoreAnimatorStart) {
1092            this.lineWidthBegin = this.lineWidth;
1093            this.trackStartAngleBegin = this.trackStartAngle;
1094            this.startMinRestoreAnimator();
1095            this.calcBlur();
1096        }
1097    }
1098
1099    onTouchMove(touchY) {
1100        let maxAngel;
1101        let minAngel;
1102        let delta = this.delta;
1103        maxAngel = this.selectedEndAngle;
1104        minAngel = this.trackStartAngle;
1105        if (!this.options.layoutOptions.reverse) {
1106            delta = -this.delta;
1107        }
1108        const isMaxFitted = !(delta < 0 && nearEqual(maxAngel, this.activeEndAngle));
1109        const isMinFitted = !(delta > 0 && nearEqual(this.trackStartAngle, this.activeStartAngle)) &&
1110        nearEqual(this.options.valueOptions.progress, this.options.valueOptions.min);
1111        const isMaxNearEqual = nearEqual(maxAngel, this.activeEndAngle);
1112        const isMinNearEqual = nearEqual(minAngel, this.activeStartAngle);
1113        if (this.isAntiClock) {
1114            const isCalcMax = (maxAngel < this.activeEndAngle || isMaxNearEqual) && isMaxFitted;
1115            const isCalcMin = (minAngel >= this.activeStartAngle || isMinNearEqual) && isMinFitted;
1116            if (isCalcMax) {
1117                this.selectedMaxOrMin = AnimatorStatus.MAX;
1118                this.calcMaxValue(touchY);
1119            }
1120            else if (isCalcMin) {
1121                this.selectedMaxOrMin = AnimatorStatus.MIN;
1122                this.calcMinValue(touchY);
1123            }
1124            else {
1125                this.calcValue(touchY);
1126                this.selectedMaxOrMin = AnimatorStatus.NORMAL;
1127            }
1128        }
1129        else {
1130            const isCalcMax = (maxAngel > this.activeEndAngle || isMaxNearEqual) && isMaxFitted;
1131            const isCalcMin = (minAngel <= this.activeStartAngle || isMinNearEqual) && isMinFitted;
1132            if (isCalcMax) {
1133                this.selectedMaxOrMin = AnimatorStatus.MAX;
1134                this.calcMaxValue(touchY);
1135            }
1136            else if (isCalcMin) {
1137                this.selectedMaxOrMin = AnimatorStatus.MIN;
1138                this.calcMinValue(touchY);
1139            }
1140            else {
1141                this.calcValue(touchY);
1142                this.selectedMaxOrMin = AnimatorStatus.NORMAL;
1143            }
1144        }
1145    }
1146
1147    onDigitalCrownEvent(event) {
1148        this.timeCur = systemDateTime.getTime(false);
1149        if (event.action === CrownAction.BEGIN && !this.isEnlarged) {
1150            this.clearTimeout();
1151            this.isEnlarged = true;
1152            this.startTouchAnimator();
1153            this.calcBlur();
1154        }
1155        else if ((event.action === CrownAction.BEGIN || CrownAction.UPDATE) && this.isEnlarged) {
1156            this.clearTimeout();
1157            this.crownDeltaAngle = this.getUIContext().px2vp(-event.degree *
1158            this.calcDisplayControlRatio(this.options.digitalCrownSensitivity)) / this.radius;
1159            this.calcCrownValue(this.crownDeltaAngle);
1160            this.setVibration();
1161        }
1162        else if ((this.isEnlarged) && (this.isTouchAnimatorFinished) && (event.action === CrownAction.UPDATE)) {
1163            this.clearTimeout();
1164            this.crownDeltaAngle = this.getUIContext().px2vp(-event.degree *
1165            this.calcDisplayControlRatio(this.options.digitalCrownSensitivity)) / this.radius;
1166            this.calcCrownValue(this.crownDeltaAngle);
1167        }
1168        else if (this.isEnlarged && event.action === CrownAction.END) {
1169            this.clearTimeout();
1170            this.meter = setTimeout(() => {
1171                if (this.isEnlarged) {
1172                    this.isTouchAnimatorFinished = false;
1173                    this.isEnlarged = false;
1174                    this.startRestoreAnimator();
1175                    this.calcBlur();
1176                }
1177            }, RESTORE_TIMEOUT);
1178        }
1179    }
1180
1181    setVibration() {
1182        const isMaxOrMin = this.options.valueOptions.progress === this.options.valueOptions.max ||
1183            this.options.valueOptions.progress === this.options.valueOptions.min;
1184        if (this.timeCur - this.timePre >= CROWN_TIME_FLAG && !isMaxOrMin) {
1185            try {
1186                this.startVibration();
1187            }
1188            catch (error) {
1189                const e = error;
1190                hilog.error(0x3900, 'ArcSlider', `An unexpected error occurred in starting vibration.
1191                      Code: ${e.code}, message: ${e.message}`);
1192            }
1193            this.timePre = this.timeCur;
1194        }
1195    }
1196
1197    startVibration() {
1198        const ret = vibrator.isSupportEffectSync(VIBRATOR_TYPE_TWO);
1199        if (ret) {
1200            vibrator.startVibration({
1201                type: 'preset',
1202                effectId: VIBRATOR_TYPE_TWO,
1203                count: 1,
1204            }, {
1205                usage: 'unknown'
1206            }, (error) => {
1207                if (error) {
1208                    hilog.error(0x3900, 'ArcSlider', `Failed to start vibration.
1209                            Code: ${error.code}, message: ${error.message}`);
1210                    this.timePre = this.timeCur;
1211                    return;
1212                }
1213                hilog.info(0x3900, 'ArcSlider', 'Succeed in starting vibration');
1214            });
1215        }
1216        else {
1217            hilog.error(0x3900, 'ArcSlider', VIBRATOR_TYPE_TWO + ` is not supported`);
1218        }
1219    }
1220
1221    initialRender() {
1222        this.observeComponentCreation2((elmtId, isInitialRender) => {
1223            Stack.create();
1224            Stack.clipShape(new PathShape().commands(this.clipPath));
1225            Stack.onTouchIntercept((event) => {
1226                if (this.isHotRegion(event.touches[0].x, event.touches[0].y)) {
1227                    return HitTestMode.Default;
1228                }
1229                return HitTestMode.Transparent;
1230            });
1231        }, Stack);
1232        this.observeComponentCreation2((elmtId, isInitialRender) => {
1233            Circle.create({ width: this.diameter, height: this.diameter });
1234            Circle.width(this.diameter);
1235            Circle.height(this.diameter);
1236            Circle.fill(BLUR_COLOR_DEFAULT);
1237            Circle.backdropBlur(this.options.styleOptions.trackBlur);
1238        }, Circle);
1239        this.observeComponentCreation2((elmtId, isInitialRender) => {
1240            Button.createWithLabel();
1241            Button.stateEffect(false);
1242            Button.backgroundColor(BLUR_COLOR_DEFAULT);
1243            Button.drawModifier(this.fullModifier);
1244            Button.width(this.diameter);
1245            Button.height(this.diameter);
1246            Button.onTouch((event) => {
1247                if (event) {
1248                    this.onTouchEvent(event);
1249                }
1250            });
1251            Button.onTouchIntercept((event) => {
1252                if (this.isHotRegion(event.touches[0].x, event.touches[0].y)) {
1253                    return HitTestMode.Block;
1254                }
1255                return HitTestMode.Transparent;
1256            });
1257            Button.focusable(true);
1258            Button.focusOnTouch(true);
1259            Button.onDigitalCrown((event) => {
1260                if (event && this.isFocus) {
1261                    this.onDigitalCrownEvent(event);
1262                }
1263                this.options.onChange?.(this.options.valueOptions.progress);
1264            });
1265        }, Button);
1266        Button.pop();
1267        Stack.pop();
1268    }
1269
1270    updateStateVars(params) {
1271        if (params === undefined) {
1272            return;
1273        }
1274        if ("options" in params) {
1275            this.updateParam("options", params.options);
1276        }
1277    }
1278
1279    rerender() {
1280        this.updateDirtyElements();
1281    }
1282}
1283__decorate([
1284    Param
1285], ArcSlider.prototype, "options", void 0);
1286__decorate([
1287    Local
1288], ArcSlider.prototype, "lineWidth", void 0);
1289__decorate([
1290    Local
1291], ArcSlider.prototype, "radius", void 0);
1292__decorate([
1293    Local
1294], ArcSlider.prototype, "trackStartAngle", void 0);
1295__decorate([
1296    Local
1297], ArcSlider.prototype, "trackEndAngle", void 0);
1298__decorate([
1299    Local
1300], ArcSlider.prototype, "selectedStartAngle", void 0);
1301__decorate([
1302    Local
1303], ArcSlider.prototype, "selectedEndAngle", void 0);
1304__decorate([
1305    Local
1306], ArcSlider.prototype, "selectRatioNow", void 0);
1307__decorate([
1308    Local
1309], ArcSlider.prototype, "isEnlarged", void 0);
1310__decorate([
1311    Local
1312], ArcSlider.prototype, "clipPath", void 0);
1313__decorate([
1314    Local
1315], ArcSlider.prototype, "isReverse", void 0);
1316__decorate([
1317    Local
1318], ArcSlider.prototype, "isLargeArc", void 0);
1319__decorate([
1320    Local
1321], ArcSlider.prototype, "isFocus", void 0);
1322__decorate([
1323    Monitor('trackStartAngle', 'trackEndAngle', 'selectedStartAngle', 'selectedEndAngle', 'options.valueOptions.min', 'options.valueOptions.max', 'options.valueOptions.progress', 'options.layoutOptions.reverse', 'options.layoutOptions.position', 'options.styleOptions.trackThickness', 'options.styleOptions.activeTrackThickness', 'options.styleOptions.trackColor', 'options.styleOptions.selectedColor', 'options.styleOptions.trackBlur', 'clipPath', 'isFocus', 'isAntiClock')
1324], ArcSlider.prototype, "onChange", null);
1325
1326
1327export default {
1328    ArcSlider,
1329    ArcSliderPosition,
1330    ArcSliderOptions,
1331    ArcSliderValueOptions,
1332    ArcSliderLayoutOptions,
1333    ArcSliderStyleOptions
1334};
1335