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 16let __decorate = 17 (this && this.__decorate) || 18 function (decorators, target, key, desc) { 19 let c = arguments.length; 20 let r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc; 21 let d; 22 if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function') { 23 r = Reflect.decorate(decorators, target, key, desc); 24 } else { 25 for (let i = decorators.length - 1; i >= 0; i--) { 26 d = decorators[i]; 27 if (d) { 28 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 29 } 30 } 31 } 32 return c > 3 && r && Object.defineProperty(target, key, r), r; 33}; 34if (!('finalizeConstruction' in ViewPU.prototype)) { 35 Reflect.set(ViewPU.prototype, 'finalizeConstruction', () => {}); 36} 37 38const measure = requireNapi('measure'); 39const Curves = globalThis.requireNativeModule('ohos.curves'); 40const LengthMetrics = requireNapi('arkui.node').LengthMetrics; 41const ColorMetrics = requireNapi('arkui.node').ColorMetrics; 42const LengthUnit = requireNapi('arkui.node').LengthUnit; 43const PathShape = requireNapi('arkui.shape').PathShape; 44 45export let ArcButtonPosition; 46(function (ArcButtonPosition) { 47 ArcButtonPosition[(ArcButtonPosition['TOP_EDGE'] = 0)] = 'TOP_EDGE'; 48 ArcButtonPosition[(ArcButtonPosition['BOTTOM_EDGE'] = 1)] = 'BOTTOM_EDGE'; 49})(ArcButtonPosition || (ArcButtonPosition = {})); 50 51export let ArcButtonStyleMode; 52(function (ArcButtonStyleMode) { 53 ArcButtonStyleMode[(ArcButtonStyleMode['EMPHASIZED_LIGHT'] = 0)] = 54 'EMPHASIZED_LIGHT'; 55 ArcButtonStyleMode[(ArcButtonStyleMode['EMPHASIZED_DARK'] = 1)] = 56 'EMPHASIZED_DARK'; 57 ArcButtonStyleMode[(ArcButtonStyleMode['NORMAL_LIGHT'] = 2)] = 'NORMAL_LIGHT'; 58 ArcButtonStyleMode[(ArcButtonStyleMode['NORMAL_DARK'] = 3)] = 'NORMAL_DARK'; 59 ArcButtonStyleMode[(ArcButtonStyleMode['CUSTOM'] = 4)] = 'CUSTOM'; 60})(ArcButtonStyleMode || (ArcButtonStyleMode = {})); 61 62export let ArcButtonStatus; 63(function (ArcButtonStatus) { 64 ArcButtonStatus[(ArcButtonStatus['NORMAL'] = 0)] = 'NORMAL'; 65 ArcButtonStatus[(ArcButtonStatus['PRESSED'] = 1)] = 'PRESSED'; 66 ArcButtonStatus[(ArcButtonStatus['DISABLED'] = 2)] = 'DISABLED'; 67})(ArcButtonStatus || (ArcButtonStatus = {})); 68 69class Constants {} 70 71/** 72 * 最大文字大小 73 */ 74Constants.MAX_FONT_SIZE = 19; 75/** 76 * 最小文字大小 77 */ 78Constants.MIN_FONT_SIZE = 13; 79/** 80 * 阴影半径 81 */ 82Constants.SHADOW_BLUR = 4; 83/** 84 * Y偏移 85 */ 86Constants.SHADOW_OFFSET_Y = 3; 87/** 88 * 按钮与边框距离 89 */ 90Constants.DISTANCE_FROM_BORDER = 1; 91/** 92 * 文本间距 93 */ 94Constants.TEXT_HORIZONTAL_MARGIN = 24; 95Constants.TEXT_MARGIN_TOP = 10; 96Constants.TEXT_MARGIN_BOTTOM = 16; 97Constants.EMPHASIZED_TEXT_COLOR = '#FFFFFF'; 98Constants.EMPHASIZED_PRESSED_BTN_COLOR = '#357FFF'; 99Constants.EMPHASIZED_DISABLE_BTN_COLOR = '#1F71FF'; 100Constants.EMPHASIZED_DISABLE_TEXT_COLOR = '#FFFFFF'; 101Constants.NORMAL_LIGHT_NORMAL_BTN_COLOR = '#17273F'; 102Constants.NORMAL_LIGHT_TEXT_COLOR = '#5EA1FF'; 103Constants.NORMAL_LIGHT_PRESSED_BTN_COLOR = '#2E3D52'; 104Constants.NORMAL_LIGHT_DISABLE_BTN_COLOR = '#17273F'; 105Constants.NORMAL_LIGHT_DISABLE_TEXT_COLOR = '#995ea1ff'; 106Constants.NORMAL_DARK_NORMAL_BTN_COLOR = '#252525'; 107Constants.NORMAL_DARK_TEXT_COLOR = '#5EA1FF'; 108Constants.NORMAL_DARK_PRESSED_BTN_COLOR = '#3B3B3B'; 109Constants.NORMAL_DARK_DISABLE_BTN_COLOR = '#262626'; 110Constants.NORMAL_DARK_DISABLE_TEXT_COLOR = '#995ea1ff'; 111Constants.EMPHASIZEWARN_NORMAL_BTN_COLOR = '#BF2629'; 112Constants.EMPHASIZEWARN_TEXT_COLOR = '#FFFFFF'; 113Constants.EMPHASIZEWARN_PRESSED_BTN_COLOR = '#C53C3E'; 114Constants.EMPHASIZEWARN_DISABLE_BTN_COLOR = '#4C0f10'; 115Constants.EMPHASIZEWARN_DISABLE_TEXT_COLOR = '#99FFFFFF'; 116Constants.DEFAULT_TRANSPARENCY = 0.4; 117Constants.EMPHASIZED_NORMAL_BTN_COLOR = { 118 id: -1, 119 type: 10001, 120 params: ['sys.color.comp_background_emphasize'], 121 bundleName: '__harDefaultBundleName__', 122 moduleName: '__harDefaultModuleName__', 123} 124 125let ArcButtonOptions = class ArcButtonOptions { 126 constructor(options) { 127 this.position = options.position ?? ArcButtonPosition.BOTTOM_EDGE; 128 this.styleMode = options.styleMode ?? ArcButtonStyleMode.EMPHASIZED_LIGHT; 129 this.status = options.status ?? ArcButtonStatus.NORMAL; 130 this.label = options.label ?? ''; 131 this.backgroundBlurStyle = options.backgroundBlurStyle ?? BlurStyle.NONE; 132 this.backgroundColor = 133 options.backgroundColor ?? ColorMetrics.resourceColor(Color.Black); 134 this.shadowColor = 135 options.shadowColor ?? ColorMetrics.resourceColor('#000000'); 136 this.shadowEnabled = options.shadowEnabled ?? false; 137 this.fontSize = 138 options.fontSize ?? new LengthMetrics(Constants.MAX_FONT_SIZE); 139 this.fontColor = 140 options.fontColor ?? ColorMetrics.resourceColor(Color.White); 141 this.pressedFontColor = 142 options.pressedFontColor ?? ColorMetrics.resourceColor(Color.White); 143 this.fontStyle = options.fontStyle ?? FontStyle.Normal; 144 this.fontFamily = options.fontFamily ?? ''; 145 this.fontMargin = options.fontMargin ?? { 146 start: LengthMetrics.vp(Constants.TEXT_HORIZONTAL_MARGIN), 147 top: LengthMetrics.vp(Constants.TEXT_MARGIN_TOP), 148 end: LengthMetrics.vp(Constants.TEXT_HORIZONTAL_MARGIN), 149 bottom: LengthMetrics.vp(Constants.TEXT_MARGIN_BOTTOM), 150 }; 151 this.onTouch = options.onTouch ?? (() => {}); 152 this.onClick = options.onClick ?? (() => {}); 153 } 154}; 155__decorate([Trace], ArcButtonOptions.prototype, 'position', void 0); 156__decorate([Trace], ArcButtonOptions.prototype, 'styleMode', void 0); 157__decorate([Trace], ArcButtonOptions.prototype, 'status', void 0); 158__decorate([Trace], ArcButtonOptions.prototype, 'label', void 0); 159__decorate([Trace], ArcButtonOptions.prototype, 'backgroundBlurStyle', void 0); 160__decorate([Trace], ArcButtonOptions.prototype, 'backgroundColor', void 0); 161__decorate([Trace], ArcButtonOptions.prototype, 'shadowColor', void 0); 162__decorate([Trace], ArcButtonOptions.prototype, 'shadowEnabled', void 0); 163__decorate([Trace], ArcButtonOptions.prototype, 'fontSize', void 0); 164__decorate([Trace], ArcButtonOptions.prototype, 'fontColor', void 0); 165__decorate([Trace], ArcButtonOptions.prototype, 'pressedFontColor', void 0); 166__decorate([Trace], ArcButtonOptions.prototype, 'fontStyle', void 0); 167__decorate([Trace], ArcButtonOptions.prototype, 'fontFamily', void 0); 168__decorate([Trace], ArcButtonOptions.prototype, 'fontMargin', void 0); 169__decorate([Trace], ArcButtonOptions.prototype, 'onTouch', void 0); 170__decorate([Trace], ArcButtonOptions.prototype, 'onClick', void 0); 171ArcButtonOptions = __decorate([ObservedV2], ArcButtonOptions); 172 173export { ArcButtonOptions }; 174 175export class ArcButton extends ViewV2 { 176 constructor( 177 parent, 178 params, 179 __localStorage, 180 elmtId = -1, 181 paramsLambda, 182 extraInfo 183 ) { 184 super(parent, elmtId, extraInfo); 185 this.initParam( 186 'options', 187 params && 'options' in params ? params.options : undefined 188 ); 189 this.canvasWidth = 0; 190 this.canvasHeight = 0; 191 this.scaleX = 1; 192 this.scaleY = 1; 193 this.btnColor = ColorMetrics.resourceColor(Color.Black); 194 this.textWidth = 0; 195 this.textHeight = 0; 196 this.fontColor = ColorMetrics.resourceColor(Color.White); 197 this.isExceed = false; 198 this.pathString = ''; 199 this.fontSize = ''; 200 this.btnNormalColor = ColorMetrics.resourceColor(Color.Black); 201 this.btnPressColor = ColorMetrics.resourceColor(Color.Black); 202 this.btnDisableColor = ColorMetrics.resourceColor(Color.Black); 203 this.textNormalColor = ColorMetrics.resourceColor(Color.White); 204 this.textDisableColor = ColorMetrics.resourceColor(Color.White); 205 this.isUp = false; 206 this.curves = Curves.interpolatingSpring(10, 1, 350, 35); 207 this.scaleValue = 1; 208 this.textPressColor = ColorMetrics.resourceColor(Color.White); 209 this.arcButtonTheme = { 210 BUTTON_HEIGHT: this.getArcButtonThemeVpValue({ 211 id: -1, 212 type: 10002, 213 params: ['sys.float.arc_button_height'], 214 bundleName: '__harDefaultBundleName__', 215 moduleName: '__harDefaultModuleName__', 216 }), 217 ARC_CIRCLE_DIAMETER: this.getArcButtonThemeVpValue({ 218 id: -1, 219 type: 10002, 220 params: ['sys.float.arc_button_auxiliary_circle_diameter'], 221 bundleName: '__harDefaultBundleName__', 222 moduleName: '__harDefaultModuleName__', 223 }), 224 DIAL_CIRCLE_DIAMETER: this.getArcButtonThemeVpValue({ 225 id: -1, 226 type: 10002, 227 params: ['sys.float.arc_button_dial_circle_diameter'], 228 bundleName: '__harDefaultBundleName__', 229 moduleName: '__harDefaultModuleName__', 230 }), 231 CHAMFER_CIRCLE_RADIUS: this.getArcButtonThemeVpValue({ 232 id: -1, 233 type: 10002, 234 params: ['sys.float.arc_button_chamfer_radius'], 235 bundleName: '__harDefaultBundleName__', 236 moduleName: '__harDefaultModuleName__', 237 }), 238 }; 239 this.dataProcessUtil = new DataProcessUtil(this.arcButtonTheme); 240 this.finalizeConstruction(); 241 } 242 243 optionsChange() { 244 this.fontSize = this.cover(this.options.fontSize); 245 this.judgeTextWidth(); 246 this.changeStatus(); 247 } 248 249 changeStatus() { 250 switch (this.options.styleMode) { 251 case ArcButtonStyleMode.EMPHASIZED_LIGHT: 252 this.btnNormalColor = ColorMetrics.resourceColor( 253 Constants.EMPHASIZED_NORMAL_BTN_COLOR 254 ); 255 this.textNormalColor = ColorMetrics.resourceColor( 256 Constants.EMPHASIZED_TEXT_COLOR 257 ); 258 this.btnPressColor = ColorMetrics.resourceColor( 259 Constants.EMPHASIZED_PRESSED_BTN_COLOR 260 ); 261 this.btnDisableColor = ColorMetrics.resourceColor( 262 Constants.EMPHASIZED_DISABLE_BTN_COLOR 263 ); 264 this.textDisableColor = ColorMetrics.resourceColor( 265 Constants.EMPHASIZED_DISABLE_TEXT_COLOR 266 ); 267 this.textPressColor = ColorMetrics.resourceColor( 268 Constants.EMPHASIZED_TEXT_COLOR 269 ); 270 break; 271 case ArcButtonStyleMode.NORMAL_LIGHT: 272 this.btnNormalColor = ColorMetrics.resourceColor( 273 Constants.NORMAL_LIGHT_NORMAL_BTN_COLOR 274 ); 275 this.textNormalColor = ColorMetrics.resourceColor( 276 Constants.NORMAL_LIGHT_TEXT_COLOR 277 ); 278 this.btnPressColor = ColorMetrics.resourceColor( 279 Constants.NORMAL_LIGHT_PRESSED_BTN_COLOR 280 ); 281 this.btnDisableColor = ColorMetrics.resourceColor( 282 Constants.NORMAL_LIGHT_DISABLE_BTN_COLOR 283 ); 284 this.textDisableColor = ColorMetrics.resourceColor( 285 Constants.NORMAL_LIGHT_DISABLE_TEXT_COLOR 286 ); 287 this.textPressColor = ColorMetrics.resourceColor( 288 Constants.NORMAL_LIGHT_TEXT_COLOR 289 ); 290 break; 291 case ArcButtonStyleMode.NORMAL_DARK: 292 this.btnNormalColor = ColorMetrics.resourceColor( 293 Constants.NORMAL_DARK_NORMAL_BTN_COLOR 294 ); 295 this.textNormalColor = ColorMetrics.resourceColor( 296 Constants.NORMAL_DARK_TEXT_COLOR 297 ); 298 this.btnPressColor = ColorMetrics.resourceColor( 299 Constants.NORMAL_DARK_PRESSED_BTN_COLOR 300 ); 301 this.btnDisableColor = ColorMetrics.resourceColor( 302 Constants.NORMAL_DARK_DISABLE_BTN_COLOR 303 ); 304 this.textDisableColor = ColorMetrics.resourceColor( 305 Constants.NORMAL_DARK_DISABLE_TEXT_COLOR 306 ); 307 this.textPressColor = ColorMetrics.resourceColor( 308 Constants.NORMAL_DARK_TEXT_COLOR 309 ); 310 break; 311 case ArcButtonStyleMode.EMPHASIZED_DARK: 312 this.btnNormalColor = ColorMetrics.resourceColor( 313 Constants.EMPHASIZEWARN_NORMAL_BTN_COLOR 314 ); 315 this.textNormalColor = ColorMetrics.resourceColor( 316 Constants.EMPHASIZEWARN_TEXT_COLOR 317 ); 318 this.btnPressColor = ColorMetrics.resourceColor( 319 Constants.EMPHASIZEWARN_PRESSED_BTN_COLOR 320 ); 321 this.btnDisableColor = ColorMetrics.resourceColor( 322 Constants.EMPHASIZEWARN_DISABLE_BTN_COLOR 323 ); 324 this.textDisableColor = ColorMetrics.resourceColor( 325 Constants.EMPHASIZEWARN_DISABLE_TEXT_COLOR 326 ); 327 this.textPressColor = ColorMetrics.resourceColor( 328 Constants.EMPHASIZEWARN_TEXT_COLOR 329 ); 330 break; 331 default: 332 this.btnNormalColor = this.options.backgroundColor; 333 this.textNormalColor = this.options.fontColor; 334 this.btnPressColor = this.options.backgroundColor; 335 this.textPressColor = this.options.pressedFontColor; 336 break; 337 } 338 if (this.options.status === ArcButtonStatus.DISABLED) { 339 this.btnColor = this.btnDisableColor; 340 this.fontColor = this.textDisableColor; 341 } else { 342 this.btnColor = this.btnNormalColor; 343 this.fontColor = this.textNormalColor; 344 } 345 } 346 347 /** 348 * 初始化数据 349 */ 350 initValues() { 351 this.isUp = this.options.position == ArcButtonPosition.TOP_EDGE; 352 this.btnColor = this.options.backgroundColor; 353 this.fontColor = this.options.fontColor; 354 this.curves = Curves.interpolatingSpring(10, 1, 350, 35); 355 this.scaleValue = 0.95; 356 this.changeStatus(); 357 } 358 359 getArcButtonThemeVpValue(res) { 360 if (!res) { 361 return 0; 362 } 363 let metrics = LengthMetrics.resource(res); 364 let value = metrics.value; 365 switch (metrics.unit) { 366 case LengthUnit.PX: 367 return px2vp(value); 368 case LengthUnit.LPX: 369 return px2vp(lpx2px(value)); 370 case LengthUnit.FP: 371 return px2vp(fp2px(value)); 372 } 373 return value; 374 } 375 376 /** 377 * 判断是否超出文本框宽度 378 */ 379 judgeTextWidth() { 380 const measureTextWidth = measure.measureText({ 381 textContent: this.options.label, 382 fontStyle: this.options.fontStyle, 383 fontFamily: this.options.fontFamily, 384 fontWeight: FontWeight.Medium, 385 maxLines: 1, 386 fontSize: `${Constants.MIN_FONT_SIZE}fp`, 387 }); 388 this.isExceed = 389 measureTextWidth > this.getUIContext().vp2px(this.textWidth); 390 } 391 392 aboutToAppear() { 393 if (this.arcButtonTheme.BUTTON_HEIGHT === 0) { 394 console.error("arcbutton can't obtain sys float value."); 395 return; 396 } 397 this.initValues(); 398 this.dataProcessUtil.initData(); 399 const pathData = this.dataProcessUtil.calculate(); 400 this.generatePath(pathData); 401 } 402 403 calculateActualPosition(pos, canvasTopPos) { 404 const x = this.getUIContext().vp2px(pos.x - canvasTopPos.x); 405 const y = this.getUIContext().vp2px(pos.y - canvasTopPos.y); 406 return new ArcButtonPoint(x, y); 407 } 408 409 generatePath(data) { 410 if (data == null) { 411 return; 412 } 413 this.canvasWidth = data.btnWidth + Constants.SHADOW_BLUR * 2; 414 this.canvasHeight = data.btnHeight + Constants.DISTANCE_FROM_BORDER * 2; 415 const margin = this.options.fontMargin; 416 const start = margin?.start?.value ?? 0; 417 const end = margin?.end?.value ?? 0; 418 const top = margin?.top?.value ?? 0; 419 const bottom = margin?.bottom?.value ?? 0; 420 this.textWidth = data.btnWidth - start - end; 421 this.textHeight = data.btnHeight - top - bottom; 422 this.judgeTextWidth(); 423 const canvasLeftTopPoint = data.canvasLeftTop; 424 canvasLeftTopPoint.x -= Constants.SHADOW_BLUR; 425 canvasLeftTopPoint.y -= Constants.DISTANCE_FROM_BORDER; 426 const leftTopPoint = this.calculateActualPosition( 427 data.leftTopPoint, 428 canvasLeftTopPoint 429 ); 430 const upperArcCircleR = this.getUIContext().vp2px( 431 this.arcButtonTheme.ARC_CIRCLE_DIAMETER / 2 432 ); 433 const rightTopPoint = this.calculateActualPosition( 434 data.rightTopPoint, 435 canvasLeftTopPoint 436 ); 437 const chamferCircleR = this.getUIContext().vp2px( 438 this.arcButtonTheme.CHAMFER_CIRCLE_RADIUS 439 ); 440 const rightBottomPoint = this.calculateActualPosition( 441 data.rightBottomPoint, 442 canvasLeftTopPoint 443 ); 444 const lowerArcCircleR = this.getUIContext().vp2px( 445 this.arcButtonTheme.DIAL_CIRCLE_DIAMETER / 2 446 ); 447 const leftBottomPoint = this.calculateActualPosition( 448 data.leftBottomPoint, 449 canvasLeftTopPoint 450 ); 451 const pathStr = 452 `M ${leftTopPoint.x} ${leftTopPoint.y} A ${upperArcCircleR} ${upperArcCircleR}, 0, 0, 0, 453 ${rightTopPoint.x} ${rightTopPoint.y}` + 454 `Q ${rightTopPoint.x - chamferCircleR * 1.2} ${ 455 rightTopPoint.y + chamferCircleR * 0.6 456 } ${rightBottomPoint.x} ${rightBottomPoint.y}` + 457 `A ${lowerArcCircleR} ${lowerArcCircleR}, 0, 0, 0, ${leftBottomPoint.x} 458 ${leftBottomPoint.y}` + 459 `Q ${leftTopPoint.x + chamferCircleR * 1.2} ${ 460 leftTopPoint.y + chamferCircleR * 0.6 461 } ${leftTopPoint.x} ${leftTopPoint.y}`; 462 this.pathString = pathStr; 463 } 464 465 TextBuilderIsExceed(parent = null) { 466 this.observeComponentCreation2((elmtId, isInitialRender) => { 467 Text.create(this.options.label); 468 Text.width(this.textWidth); 469 Text.height(this.textHeight); 470 Text.fontColor(this.fontColor.color); 471 Text.fontSize(this.fontSize); 472 Text.maxLines(1); 473 Text.textAlign(TextAlign.Center); 474 Text.fontWeight(FontWeight.Medium); 475 Text.fontStyle(this.options.fontStyle); 476 Text.fontFamily(this.options.fontFamily); 477 Text.backgroundColor(Color.Transparent); 478 Text.textOverflow({ overflow: TextOverflow.MARQUEE }); 479 Text.margin({ 480 start: this.options.fontMargin.start, 481 top: this.isUp 482 ? this.options.fontMargin.bottom 483 : this.options.fontMargin.top, 484 end: this.options.fontMargin.end, 485 bottom: this.options.fontMargin.bottom, 486 }); 487 }, Text); 488 Text.pop(); 489 } 490 491 TextBuilderNormal(parent = null) { 492 this.observeComponentCreation2((elmtId, isInitialRender) => { 493 Text.create(this.options.label); 494 Text.width(this.textWidth); 495 Text.height(this.textHeight); 496 Text.textAlign(TextAlign.Center); 497 Text.fontColor(this.fontColor.color); 498 Text.maxFontSize(`${Constants.MAX_FONT_SIZE}fp`); 499 Text.minFontSize(`${Constants.MIN_FONT_SIZE}fp`); 500 Text.fontWeight(FontWeight.Medium); 501 Text.fontStyle(this.options.fontStyle); 502 Text.fontFamily(this.options.fontFamily); 503 Text.maxLines(1); 504 Text.margin({ 505 start: this.options.fontMargin.start, 506 top: this.isUp 507 ? this.options.fontMargin.bottom 508 : this.options.fontMargin.top, 509 end: this.options.fontMargin.end, 510 bottom: this.options.fontMargin.bottom, 511 }); 512 }, Text); 513 Text.pop(); 514 } 515 516 cover(params) { 517 switch (params.unit) { 518 case LengthUnit.VP: 519 return `${params.value}vp`; 520 case LengthUnit.PX: 521 return `${params.value}px`; 522 case LengthUnit.FP: 523 return `${params.value}fp`; 524 case LengthUnit.LPX: 525 return `${params.value}lpx`; 526 case LengthUnit.PERCENT: 527 return `${params.value}%`; 528 } 529 } 530 531 getShadow() { 532 if (!this.options.shadowEnabled) { 533 return undefined; 534 } 535 return { 536 radius: Constants.SHADOW_BLUR, 537 color: this.options.shadowColor.color, 538 offsetY: Constants.SHADOW_OFFSET_Y, 539 }; 540 } 541 542 initialRender() { 543 this.observeComponentCreation2((elmtId, isInitialRender) => { 544 Stack.create({ alignContent: Alignment.Center }); 545 Context.animation({ curve: this.curves }); 546 Stack.enabled(this.options.status !== ArcButtonStatus.DISABLED); 547 Stack.opacity( 548 this.options.styleMode === ArcButtonStyleMode.EMPHASIZED_LIGHT && 549 this.options.status === ArcButtonStatus.DISABLED 550 ? Constants.DEFAULT_TRANSPARENCY 551 : 1 552 ); 553 Context.animation(null); 554 Stack.width(this.canvasWidth); 555 Stack.height(this.canvasHeight); 556 Stack.scale({ 557 x: this.scaleX, 558 y: this.scaleY, 559 centerY: this.isUp ? 0 : this.canvasHeight, 560 }); 561 Stack.onTouch((event) => { 562 this.dealTouchEvent(event); 563 }); 564 Stack.onClick((event) => { 565 if (this.options.onClick) { 566 this.options.onClick(event); 567 } 568 }); 569 }, Stack); 570 this.observeComponentCreation2((elmtId, isInitialRender) => { 571 Button.createWithLabel({ type: ButtonType.Normal, stateEffect: true }); 572 Button.width('100%'); 573 Button.height('100%'); 574 Button.rotate({ angle: !this.isUp ? 0 : 180 }); 575 Button.clipShape(new Path({ commands: this.pathString })); 576 Button.backgroundColor(this.btnColor.color); 577 Button.backgroundBlurStyle(this.options.backgroundBlurStyle, undefined, { disableSystemAdaptation: true }); 578 Button.shadow(this.getShadow()); 579 }, Button); 580 Button.pop(); 581 this.observeComponentCreation2((elmtId, isInitialRender) => { 582 If.create(); 583 if (this.isExceed) { 584 this.ifElseBranchUpdateFunction(0, () => { 585 this.TextBuilderIsExceed.bind(this)(this); 586 }); 587 } else { 588 this.ifElseBranchUpdateFunction(1, () => { 589 this.TextBuilderNormal.bind(this)(this); 590 }); 591 } 592 }, If); 593 If.pop(); 594 Stack.pop(); 595 } 596 597 dealTouchEvent(event) { 598 const x = event.touches[0].windowX; 599 const y = event.touches[0].windowY; 600 if (this.options.onTouch) { 601 this.options.onTouch(event); 602 } 603 switch (event.type) { 604 case TouchType.Down: 605 this.scaleX = this.scaleValue; 606 this.scaleY = this.scaleValue; 607 this.btnColor = this.btnPressColor; 608 this.fontColor = this.textPressColor; 609 break; 610 case TouchType.Up: 611 this.scaleX = 1; 612 this.scaleY = 1; 613 this.btnColor = this.btnNormalColor; 614 this.fontColor = this.textNormalColor; 615 break; 616 default: 617 break; 618 } 619 } 620 621 updateStateVars(params) { 622 if (params === undefined) { 623 return; 624 } 625 if ('options' in params) { 626 this.updateParam('options', params.options); 627 } 628 } 629 630 rerender() { 631 this.updateDirtyElements(); 632 } 633} 634__decorate([Param], ArcButton.prototype, 'options', void 0); 635__decorate([Local], ArcButton.prototype, 'canvasWidth', void 0); 636__decorate([Local], ArcButton.prototype, 'canvasHeight', void 0); 637__decorate([Local], ArcButton.prototype, 'scaleX', void 0); 638__decorate([Local], ArcButton.prototype, 'scaleY', void 0); 639__decorate([Local], ArcButton.prototype, 'btnColor', void 0); 640__decorate([Local], ArcButton.prototype, 'textWidth', void 0); 641__decorate([Local], ArcButton.prototype, 'textHeight', void 0); 642__decorate([Local], ArcButton.prototype, 'fontColor', void 0); 643__decorate([Local], ArcButton.prototype, 'isExceed', void 0); 644__decorate([Local], ArcButton.prototype, 'pathString', void 0); 645__decorate([Local], ArcButton.prototype, 'fontSize', void 0); 646__decorate( 647 [ 648 Monitor( 649 'options.label', 650 'options.type', 651 'options.fontSize', 652 'options.styleMode', 653 'options.status', 654 'options.backgroundColor', 655 'options.fontColor' 656 ), 657 ], 658 ArcButton.prototype, 659 'optionsChange', 660 null 661); 662 663class DataProcessUtil { 664 constructor(theme) { 665 this.dial = new ArcButtonCircle(0, 0, 0); 666 this.arc = new ArcButtonCircle(0, 0, 0); 667 this.height = 0; 668 this.width = 0; 669 this.arcButtonTheme = undefined; 670 this.arcButtonTheme = theme; 671 } 672 673 initData() { 674 const dialRadius = this.arcButtonTheme.DIAL_CIRCLE_DIAMETER / 2; 675 this.dial = new ArcButtonCircle(dialRadius, dialRadius, dialRadius); 676 const arcRadius = this.arcButtonTheme.ARC_CIRCLE_DIAMETER / 2; 677 this.height = this.arcButtonTheme.BUTTON_HEIGHT; 678 const arcX = this.dial.center.x; 679 const arcY = this.dial.center.y + dialRadius + arcRadius - this.height; 680 this.arc = new ArcButtonCircle(arcRadius, arcX, arcY); 681 } 682 683 calculate() { 684 const chamferCircleR = this.arcButtonTheme.CHAMFER_CIRCLE_RADIUS; 685 const innerDial = new ArcButtonCircle( 686 this.dial.radius - chamferCircleR, 687 this.dial.center.x, 688 this.dial.center.y 689 ); 690 const innerArc = new ArcButtonCircle( 691 this.arc.radius - chamferCircleR, 692 this.arc.center.x, 693 this.arc.center.y 694 ); 695 const intersections = this.findCircleIntersections(innerArc, innerDial); 696 const tp1 = this.calculateIntersection( 697 this.arc.center, 698 this.arc.radius, 699 intersections[0] 700 ); 701 const tp2 = this.calculateIntersection( 702 this.arc.center, 703 this.arc.radius, 704 intersections[1] 705 ); 706 const tp3 = this.calculateIntersection( 707 this.dial.center, 708 this.dial.radius, 709 intersections[1] 710 ); 711 const tp4 = this.calculateIntersection( 712 this.dial.center, 713 this.dial.radius, 714 intersections[0] 715 ); 716 this.width = 717 this.calculateDistance(intersections[0], intersections[1]) + 718 chamferCircleR * 2; 719 const canvasLeftTop = new ArcButtonPoint( 720 intersections[0].x - chamferCircleR, 721 this.dial.center.y + this.dial.radius - this.height 722 ); 723 return new AllPoints( 724 this.width, 725 this.height, 726 tp2, 727 tp1, 728 tp3, 729 tp4, 730 canvasLeftTop 731 ); 732 } 733 734 /** 735 * 计算两点间距离 736 * @param point1 点1 737 * @param point2 点2 738 * @returns 距离 739 */ 740 calculateDistance(point1, point2) { 741 return Math.sqrt((point2.x - point1.x) ** 2 + (point2.y - point1.y) ** 2); 742 } 743 744 calculateIntersection(circleCenter, circleRadius, point) { 745 const h = circleCenter.x; 746 const k = circleCenter.y; 747 const x = point.x; 748 const y = point.y; 749 //计算直线斜率 750 let m = 0; 751 if (x != h) { 752 m = (y - k) / (x - h); 753 } else { 754 m = -1; 755 } 756 //计算截距 757 let intercept = 0; 758 if (m != -1) { 759 intercept = y - m * x; 760 } 761 //保存焦点位置 762 let resultPoint = []; 763 //判断斜率 764 if (m != -1) { 765 const a = Math.pow(m, 2) + 1; 766 const b = 2 * (m * intercept - m * k - h); 767 const c = 768 k ** 2 - 769 circleRadius ** 2 + 770 h ** 2 - 771 2 * intercept * k + 772 intercept ** 2; 773 const x1 = (-b + (b ** 2 - 4 * a * c) ** 0.5) / (2 * a); 774 const x2 = (-b - (b ** 2 - 4 * a * c) ** 0.5) / (2 * a); 775 const y1 = m * x1 + intercept; 776 const y2 = m * x2 + intercept; 777 resultPoint = [new ArcButtonPoint(x1, y1), new ArcButtonPoint(x2, y2)]; 778 } else { 779 const x1 = h; 780 const y1 = k + circleRadius; 781 const y2 = k - circleRadius; 782 resultPoint = [new ArcButtonPoint(x1, y1), new ArcButtonPoint(x1, y2)]; 783 } 784 const d1 = this.calculateDistance(resultPoint[0], point); 785 const d2 = this.calculateDistance(resultPoint[1], point); 786 if (d1 < d2) { 787 return resultPoint[0]; 788 } else { 789 return resultPoint[1]; 790 } 791 } 792 793 /** 794 * 查找两圆的交点 795 * @param C1 第一个圆 796 * @param c2 第二个圆 797 * @returns 两圆相交的点的数组 798 */ 799 findCircleIntersections(firstCircus, secondCircus) { 800 const firstCircusR = firstCircus.radius; 801 const firstCircusCenterX = firstCircus.center.x; 802 const firstCircusCenterY = firstCircus.center.y; 803 const secondCircusR = secondCircus.radius; 804 const secondCircusCenterX = secondCircus.center.x; 805 const secondCircusCenterY = secondCircus.center.y; 806 // 计算两个圆心之间的距离 807 const distance = Math.sqrt( 808 (firstCircusCenterX - secondCircusCenterX) ** 2 + 809 (firstCircusCenterY - secondCircusCenterY) ** 2 810 ); 811 // 检查异常情况 812 if (distance > firstCircusR + secondCircusR) { 813 //两个圆分离,不相交 814 return []; 815 } else if (distance < Math.abs(firstCircusR - secondCircusR)) { 816 //一个圆包含在另一个圆内,不相交 817 return []; 818 } else if (distance === 0 && firstCircusR === secondCircusR) { 819 //两个圆完全重合,具有无穷多交点 820 return []; 821 } 822 // 计算交点 823 const a = 824 (firstCircusR ** 2 - secondCircusR ** 2 + distance ** 2) / (2 * distance); 825 const h = Math.sqrt(firstCircusR ** 2 - a ** 2); 826 // 中间变量 827 const x2 = 828 firstCircusCenterX + 829 (a * (secondCircusCenterX - firstCircusCenterX)) / distance; 830 const y2 = 831 firstCircusCenterY + 832 (a * (secondCircusCenterY - firstCircusCenterY)) / distance; 833 // 交点 834 let intersection1 = new ArcButtonPoint( 835 x2 + (h * (secondCircusCenterY - firstCircusCenterY)) / distance, 836 y2 - (h * (secondCircusCenterX - firstCircusCenterX)) / distance 837 ); 838 let intersection2 = new ArcButtonPoint( 839 x2 - (h * (secondCircusCenterY - firstCircusCenterY)) / distance, 840 y2 + (h * (secondCircusCenterX - firstCircusCenterX)) / distance 841 ); 842 if (intersection1.x > intersection2.x) { 843 const mid = intersection1; 844 intersection1 = intersection2; 845 intersection2 = mid; 846 } 847 return [intersection1, intersection2]; 848 } 849} 850 851class ArcButtonCircle { 852 constructor(radius, x, y) { 853 this.radius = radius; 854 this.center = new ArcButtonPoint(x, y); 855 } 856} 857 858class ArcButtonPoint { 859 constructor(x, y) { 860 this.x = x; 861 this.y = y; 862 } 863} 864 865class AllPoints { 866 constructor( 867 btnWidth, 868 btnHeight, 869 leftTopPoint, 870 rightTopPoint, 871 leftBottomPoint, 872 rightBottomPoint, 873 canvasLeftTop 874 ) { 875 this.btnWidth = btnWidth; 876 this.btnHeight = btnHeight; 877 this.leftTopPoint = leftTopPoint; 878 this.rightTopPoint = rightTopPoint; 879 this.leftBottomPoint = leftBottomPoint; 880 this.rightBottomPoint = rightBottomPoint; 881 this.canvasLeftTop = canvasLeftTop; 882 } 883} 884 885export default { 886 ArcButton, 887 ArcButtonOptions, 888 ArcButtonPosition, 889 ArcButtonStyleMode, 890 ArcButtonStatus, 891}; 892//# sourceMappingURL=ArcButton.js.map 893