1/* 2 * Copyright (c) 2022-2023 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 { BroadCast, Constants, Log } from '@ohos/common'; 17 18const TAG: string = 'editor_PcCropRulerBar'; 19 20/** 21 * 天枢PC图库编辑使用的角度调节尺工具栏 22 */ 23@Component 24export struct PcCropRulerBar { 25 @Consume broadCast: BroadCast; 26 @State cWidth: number = 250; 27 @State cHeight: number = 57; 28 private current_def: number = 0; 29 private startPos: number = 0; 30 private setting: RenderingContextSettings = new RenderingContextSettings(true); 31 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.setting); 32 private resetClicked: Function = (): void => {}; 33 private previous: number = 0; 34 private rulerLength: number = 0 35 private rulerWidth: number = 0 36 private isVerticalScreen: boolean = true; 37 private rulerDrawHeight = 24; 38 39 iniSize() { 40 this.rulerLength = this.cWidth 41 this.rulerWidth = this.cHeight 42 } 43 44 multiScreenAdaptation() { 45 if (vp2px(Constants.NUMBER_1) == Constants.NUMBER_1) { 46 this.context.font = Constants.RULER_CONTEXT_FONT_10PX 47 } else if (vp2px(Constants.NUMBER_1) == Constants.NUMBER_2) { 48 this.context.font = Constants.RULER_CONTEXT_FONT_20PX 49 } else if (vp2px(Constants.NUMBER_1) == Constants.NUMBER_3) { 50 this.context.font = Constants.RULER_CONTEXT_FONT_30PX 51 } else { 52 this.context.font = Constants.RULER_CONTEXT_FONT_20PX 53 } 54 } 55 56 drawMidLine() { 57 // 中点 58 const mid_x = Math.floor(this.rulerLength / Constants.NUMBER_2); 59 this.context.beginPath(); 60 this.context.fillStyle = Constants.RULER_FILL_STYLE_100; 61 this.context.strokeStyle = Constants.RULER_FILL_STYLE_100; 62 this.context.lineCap = 'round'; 63 64 this.context.lineWidth = Constants.MID_LINE_WIDTH; 65 this.context.moveTo(mid_x, this.rulerDrawHeight - Constants.EDITOR_LARGE_TICK_LINE_HEIGHT); 66 this.context.lineTo(mid_x, this.rulerDrawHeight - Constants.NUMBER_1); 67 68 this.context.stroke(); 69 this.context.closePath(); 70 } 71 72 drawIntegerLine(cur_x: number, cur_num: number) { 73 this.context.moveTo(cur_x, this.rulerDrawHeight - Constants.EDITOR_MIDDLE_TICK_LINE_HEIGHT); 74 this.context.shadowBlur = Constants.RULER_LINE_WIDTH 75 this.context.lineCap = 'round'; 76 if (Math.round(cur_num) != Math.round(this.current_def) && Math.round(cur_num) == 0) { 77 this.context.textBaseline = 'bottom' 78 this.context.font = Constants.RULER_CONTEXT_FONT_25PX; 79 this.context.fillText(cur_num.toString(), cur_x, this.rulerDrawHeight - Constants.EDITOR_MIDDLE_TICK_LINE_HEIGHT); 80 } 81 this.context.lineTo(cur_x, this.rulerDrawHeight); 82 83 } 84 85 drawLine() { 86 // 起始绘制位置 87 let begin_num = this.current_def - (this.rulerLength / Constants.NUMBER_2) / Constants.NUMBER_5; 88 let end_num = this.current_def + (this.rulerLength / Constants.NUMBER_2) / Constants.NUMBER_5; 89 let cur_x = 0; 90 let cur_num = 0; 91 const scale_len = Math.ceil((this.rulerLength) / Constants.NUMBER_5) + Constants.NUMBER_1; 92 for (let i = 0; i < scale_len; i++) { 93 cur_num = begin_num + i; 94 this.context.beginPath(); 95 this.multiScreenAdaptation(); 96 this.context.textAlign = 'center'; 97 98 // 设置默认线型 99 this.context.strokeStyle = Constants.RULER_FILL_STYLE_40; 100 this.context.fillStyle = Constants.RULER_FILL_STYLE_40; 101 102 // 边缘第三根线 103 if (cur_num <= (begin_num + Constants.NUMBER_3) || cur_num >= (end_num - Constants.NUMBER_3)) { 104 this.context.strokeStyle = Constants.RULER_FILL_STYLE_30; 105 this.context.fillStyle = Constants.RULER_FILL_STYLE_30; 106 } 107 108 // 次边缘的线 109 if (cur_num <= (begin_num + Constants.NUMBER_2) || cur_num >= (end_num - Constants.NUMBER_2)) { 110 this.context.strokeStyle = Constants.RULER_FILL_STYLE_20; 111 this.context.fillStyle = Constants.RULER_FILL_STYLE_20; 112 } 113 // 最边缘的线 114 if (cur_num <= (begin_num + Constants.NUMBER_2) || cur_num >= (end_num - Constants.NUMBER_2)) { 115 this.context.strokeStyle = Constants.RULER_FILL_STYLE_10; 116 this.context.fillStyle = Constants.RULER_FILL_STYLE_10; 117 } 118 119 // 标尺0与当前数值之间的白色竖线 120 if ((cur_num < this.current_def && cur_num >= 0) || (cur_num > this.current_def && cur_num <= 0)) { 121 this.context.strokeStyle = Constants.RULER_FILL_STYLE_100; 122 this.context.fillStyle = Constants.RULER_FILL_STYLE_100; 123 } 124 125 // 设置线宽 126 this.context.shadowBlur = 0; 127 this.context.lineCap = 'round'; 128 cur_x = i * Constants.NUMBER_5 129 if (cur_x == 0 || cur_x == this.rulerLength) { 130 // 边界位置刻度线宽度为一半 131 this.context.lineWidth = (Constants.RULER_LINE_WIDTH / Constants.NUMBER_2); 132 if (cur_x < 0) { 133 cur_x = 0; 134 } 135 } else { 136 this.context.lineWidth = Constants.RULER_LINE_WIDTH; 137 } 138 139 // 绘制刻度线 140 if (Math.abs(cur_num) % Constants.NUMBER_10 === 0) { 141 // 每隔10个刻度绘制一个中刻度线 142 this.drawIntegerLine(cur_x, cur_num) 143 } else if ((cur_num < this.current_def && cur_num >= 0) || (cur_num > this.current_def && cur_num <= 0)) { 144 // 0和当前刻度之间的线 145 this.context.moveTo(cur_x, this.rulerDrawHeight - Constants.EDITOR_MIDDLE_TICK_LINE_HEIGHT); 146 this.context.lineTo(cur_x, this.rulerDrawHeight); 147 } else { 148 // 其他短刻度线 149 this.context.moveTo(cur_x, this.rulerDrawHeight - Constants.EDITOR_SMALL_TICK_LINE_HEIGHT); 150 this.context.lineTo(cur_x, this.rulerDrawHeight); 151 } 152 this.context.stroke(); 153 this.context.closePath(); 154 } 155 } 156 157 onTouchEvent(event: TouchEvent): void { 158 let axis = this.isVerticalScreen ? 'x' : 'y'; 159 if (event.type === TouchType.Down) { 160 this.startPos = event.touches[0][axis]; 161 this.previous = new Date().getTime(); 162 } 163 if (event.type !== TouchType.Move) { 164 return; 165 } 166 let now = new Date().getTime(); 167 if (now - this.previous < Constants.TIMEOUT) { 168 return; 169 } 170 this.previous = now; 171 let dir = this.startPos - event.touches[0][axis]; 172 if (Math.abs(dir / 5) < 1) { 173 return; 174 } 175 this.current_def += Number.parseInt((dir / 5).toFixed(0)); 176 this.startPos = event.touches[0][axis]; 177 if (Math.abs(this.current_def) > Constants.EDGE_ANGLE) { 178 this.current_def = this.current_def > Constants.EDGE_ANGLE ? Constants.EDGE_ANGLE : -Constants.EDGE_ANGLE; 179 } 180 this.drawRuler(); 181 this.broadCast.emit(Constants.RULER_CHANGED, [this.current_def]); 182 } 183 184 onResetClicked() { 185 this.current_def = 0; 186 this.drawRuler(); 187 } 188 189 integerAngleToString(currentAngle: number): string | undefined { 190 if (currentAngle % 10 === 0 && Math.abs(currentAngle) <= 40) { 191 return currentAngle.toString(); 192 } 193 194 return undefined; 195 } 196 197 aboutToAppear() { 198 this.resetClicked = (): void => this.onResetClicked(); 199 this.broadCast.on(Constants.CROP_RESET_CLICKED, this.resetClicked); 200 this.iniSize() 201 } 202 203 drawRuler() { 204 this.context.clearRect(0, 0, this.cWidth, this.cHeight); 205 this.drawMidLine(); 206 this.drawLine(); 207 } 208 209 aboutToDisappear() { 210 this.broadCast.off(Constants.CROP_RESET_CLICKED, this.resetClicked); 211 } 212 213 build() { 214 Flex({ 215 direction: FlexDirection.Column, 216 alignItems: ItemAlign.Center, 217 justifyContent: FlexAlign.Center 218 }) { 219 Canvas(this.context) 220 .width('100%') 221 .height('100%') 222 .onReady(() => { 223 this.drawRuler() 224 }) 225 } 226 .onTouch((event?: TouchEvent) => { 227 this.onTouchEvent(event as TouchEvent); 228 }) 229 .backgroundColor('#33000000') 230 .borderRadius($r('app.float.edit_menu_item_radius')) 231 .height($r('app.float.edit_menu_crop_ruler_bar_height')) 232 .width($r('app.float.edit_menu_crop_ruler_bar_width')) 233 .padding({ left: '12vp', right: '12vp', top: '16vp', bottom: '15vp' }) //旋转刻度尺的内边距 234 } 235} 236