1/* 2 * Copyright (c) 2022 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 16import { NavigationBar } from '../../../common/components/navigationBar' 17 18const COLOR_TRANSPARENT = '#00000000' 19const COLOR_BACKGROUND_FILL = '#7ebede' 20 21const DIAMETER = 200; 22const RADIUS_IN_PX = vp2px(DIAMETER / 2.0); 23const BIG_DIAMETER = 220; 24const BIG_RADIUS_IN_PX = vp2px(BIG_DIAMETER / 2.0); 25 26@Entry 27@Component 28struct CircleSample { 29 @State outSetValue: number = 50 30 @State pathCommands: string = '' 31 @State backGroundColor: string = '#00000000' 32 33 onPageShow() { 34 this.pathCommands = this.calPathCommands(this.outSetValue); 35 } 36 37 calXSquare(y: number) { 38 return RADIUS_IN_PX * RADIUS_IN_PX - (y - RADIUS_IN_PX) * (y - RADIUS_IN_PX); 39 } 40 41 calY(k: number) { 42 return (1 - k) * RADIUS_IN_PX * 2; 43 } 44 45 formatPathCommands(x1: number, x2: number, y: number, radius: number) { 46 return `M${x1} ${y} A${radius} ${radius} 0 ${y > RADIUS_IN_PX ? 0 : 1} 0 ${x2} ${y} ` 47 + `Q${(x1 + 3 * x2) / 4} ${y + 12.5 * (x2 - x1) / radius}, ${(x1 + x2) / 2} ${y} T${x1} ${y}` 48 } 49 50 calPathCommands(value: number) { 51 let y = this.calY(value / 100.0) 52 let squareX = this.calXSquare(y) 53 if (squareX >= 0) { 54 let x = Math.sqrt(squareX); 55 let x1 = RADIUS_IN_PX - x; 56 let x2 = RADIUS_IN_PX + x; 57 return this.formatPathCommands(x1, x2, y, RADIUS_IN_PX); 58 } 59 return '' 60 } 61 62 build() { 63 64 Column() { 65 NavigationBar({ title: '绘制组件' }) 66 67 Column() { 68 Stack() { 69 Circle({ width: BIG_DIAMETER, height: BIG_DIAMETER }) 70 .fill(COLOR_TRANSPARENT) 71 .stroke('#007DFF') 72 .strokeWidth(5) 73 Shape() { 74 Circle({ width: DIAMETER, height: DIAMETER }) 75 .fill(this.backGroundColor) 76 Path() 77 .width(DIAMETER) 78 .height(DIAMETER) 79 .commands(this.pathCommands) 80 .fill(COLOR_BACKGROUND_FILL) 81 } 82 .width(DIAMETER) 83 .height(DIAMETER) 84 85 Text(this.outSetValue.toFixed(0) + '%') 86 .fontSize(60) 87 88 } 89 .width(BIG_DIAMETER) 90 .height(BIG_DIAMETER) 91 92 Column({ space: 5 }) { 93 Row() { 94 Slider({ 95 value: this.outSetValue, 96 min: 0, 97 max: 100, 98 step: 1, 99 style: SliderStyle.OutSet 100 }) 101 .blockColor('#FFFFFF') 102 .trackColor('#182431') 103 .selectedColor('#007DFF') 104 .showSteps(true) 105 .showTips(true) 106 .onChange((value: number, mode: SliderChangeMode) => { 107 this.outSetValue = value 108 if (this.outSetValue == 100) { 109 this.backGroundColor = COLOR_BACKGROUND_FILL 110 this.pathCommands = ''; 111 } else { 112 this.backGroundColor = COLOR_TRANSPARENT 113 this.pathCommands = this.calPathCommands(this.outSetValue); 114 } 115 console.log(`value = ${value} ->` + this.pathCommands); 116 }) 117 Text(this.outSetValue.toFixed(0)).fontSize(16) 118 } 119 .padding({ top: 50 }) 120 .width('80%') 121 } 122 }.width('100%') 123 } 124 .height('100%') 125 .backgroundColor('#F1F3F5') 126 .padding({ left: '3%', right: '3%', bottom: 10 }) 127 } 128 129 pageTransition() { 130 PageTransitionEnter({ duration: 370, curve: Curve.Friction }) 131 .slide(SlideEffect.Bottom) 132 .opacity(0.0) 133 134 PageTransitionExit({ duration: 370, curve: Curve.Friction }) 135 .slide(SlideEffect.Bottom) 136 .opacity(0.0) 137 } 138}