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, ScreenManager } from '@ohos/common'; 17 18const TAG: string = 'editor_CropRulerBar'; 19 20interface RulerProperties { 21 rulerWidth: number; 22 rulerHeight: number; 23} 24 25@Component 26export struct CropRulerBar { 27 @Consume broadCast: BroadCast; 28 @Consume @Watch('iniSize') screenWidth: number; 29 @Consume @Watch('iniSize') screenHeight: number; 30 @State cWidth: number = 250; 31 @State cHeight: number = Constants.VERTICAL_RULER_COMPONENT_HEIGHT; 32 @State rulerLength: number = Constants.NUMBER_0; 33 @State rulerWidth: number = Constants.NUMBER_0; 34 @Consume('verticalScreen') isVerticalScreen: boolean; 35 private screenManager = ScreenManager.getInstance(); 36 private current_def: number = Constants.NUMBER_0; 37 private startPos: number = Constants.NUMBER_0; 38 private setting: RenderingContextSettings = new RenderingContextSettings(true); 39 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.setting); 40 private resetClicked: Function = (): void => {}; 41 private previous: number = Constants.NUMBER_0; 42 43 setRulerProperties(rulerWidth: number, rulerHeight: number): void { 44 AppStorage.SetOrCreate<RulerProperties>('rulerProperties', { 45 rulerWidth: rulerWidth, 46 rulerHeight: rulerHeight 47 } as RulerProperties) 48 } 49 50 iniSize(): void { 51 if (this.isVerticalScreen) { 52 this.rulerLength = this.cWidth; 53 this.rulerWidth = this.cHeight; 54 } else { 55 this.cWidth = Constants.HORIZONTAL_CROP_RULER_WIDTH; 56 this.cHeight = (this.screenHeight - this.screenHeight % Constants.NUMBER_20) - Constants.PADDING_HORIZONTAL; 57 this.rulerLength = this.cHeight; 58 this.rulerWidth = this.cWidth; 59 } 60 this.setRulerProperties(this.cWidth, this.cHeight); 61 } 62 63 multiScreenAdaptation(): void { 64 if (vp2px(Constants.NUMBER_1) == Constants.NUMBER_1) { 65 this.context.font = Constants.RULER_CONTEXT_FONT_10PX; 66 } else if (vp2px(Constants.NUMBER_1) == Constants.NUMBER_2) { 67 this.context.font = Constants.RULER_CONTEXT_FONT_20PX; 68 } else if (vp2px(Constants.NUMBER_1) == Constants.NUMBER_3) { 69 this.context.font = Constants.RULER_CONTEXT_FONT_30PX; 70 } else { 71 this.context.font = Constants.RULER_CONTEXT_FONT_35PX; 72 } 73 } 74 75 drawMidLine(): void { 76 const mid_x = Math.floor(this.rulerLength / Constants.NUMBER_2); 77 this.context.beginPath(); 78 this.context.fillStyle = Constants.RULER_FILL_STYLE_100; 79 if (this.isVerticalScreen) { 80 this.context.fillRect(mid_x - Constants.MID_LINE_WIDTH / Constants.NUMBER_2, 81 this.rulerWidth * Constants.NUMBER_8 / Constants.NUMBER_15, 82 Constants.MID_LINE_WIDTH, Constants.MID_LINE_HEIGHT); 83 } else { 84 this.context.fillRect(this.rulerWidth * Constants.NUMBER_8_5 / Constants.NUMBER_15, 85 mid_x - Constants.MID_LINE_WIDTH / Constants.NUMBER_2, Constants.MID_LINE_HEIGHT, 86 Constants.MID_LINE_WIDTH); 87 } 88 this.context.stroke(); 89 this.context.closePath(); 90 } 91 92 drawIntegerLine(cur_x: number, cur_num: number): void { 93 if (!this.isVerticalScreen) { 94 this.context.moveTo((this.rulerWidth * 8.5) / 15, cur_x); 95 } else { 96 this.context.moveTo(cur_x, (this.rulerWidth * 8.5) / 15); 97 } 98 99 if (Math.abs(cur_num) > Constants.EDGE_ANGLE) { 100 this.context.strokeStyle = Constants.RULER_FILL_STYLE_40; 101 this.context.shadowColor = Constants.RULER_FILL_STYLE_40; 102 } else { 103 this.context.strokeStyle = Constants.RULER_FILL_STYLE_90; 104 this.context.shadowColor = Constants.RULER_FILL_STYLE_90; 105 } 106 this.context.shadowBlur = Constants.RULER_LINE_WIDTH 107 if (Math.round(cur_num) == Math.round(this.current_def)) { 108 if (!this.isVerticalScreen) { 109 this.context.fillText(this.integerAngleToString(Math.round(cur_num)) as string, 110 (this.rulerWidth * 6) / 15, cur_x); 111 } else { 112 this.context.fillText(this.integerAngleToString(Math.round(cur_num)) as string, cur_x, 113 (this.rulerWidth * 6) / 15); 114 } 115 } else { 116 if (!this.isVerticalScreen) { 117 this.context.fillText((-cur_num).toString(), 118 (this.rulerWidth * 6) / 15, cur_x); 119 } else { 120 this.context.fillText(cur_num.toString(), cur_x, 121 (this.rulerWidth * 6) / 15); 122 } 123 124 } 125 if (!this.isVerticalScreen) { 126 this.context.lineTo(this.rulerWidth * 10.5 / 15, cur_x); 127 } else { 128 this.context.lineTo(cur_x, this.rulerWidth * 10.5 / 15); 129 } 130 } 131 132 drawLine(): void { 133 let begin_num = this.current_def - (this.rulerLength / Constants.NUMBER_2) / Constants.NUMBER_5; 134 let cur_x = 0; 135 let cur_num = 0; 136 const scale_len = Math.ceil((this.rulerLength) / Constants.NUMBER_5) + Constants.NUMBER_1; 137 for (let i = 0; i < scale_len; i++) { 138 cur_num = begin_num + i; 139 this.context.beginPath(); 140 this.multiScreenAdaptation(); 141 this.context.textAlign = 'center'; 142 if (!this.isVerticalScreen) { 143 this.context.textAlign = 'end'; 144 this.context.textBaseline = 'middle'; 145 } 146 if (Math.abs(cur_num) > Constants.EDGE_ANGLE) { 147 this.context.strokeStyle = Constants.RULER_FILL_STYLE_40; 148 this.context.fillStyle = Constants.RULER_FILL_STYLE_40; 149 } else { 150 this.context.strokeStyle = Constants.RULER_FILL_STYLE_90; 151 this.context.fillStyle = Constants.RULER_FILL_STYLE_90; 152 } 153 this.context.shadowBlur = 0; 154 cur_x = i * Constants.NUMBER_5; 155 if (cur_x == 0 || cur_x == this.rulerLength) { 156 this.context.lineWidth = (Constants.RULER_LINE_WIDTH / Constants.NUMBER_2); 157 if (cur_x < 0) { 158 cur_x = 0; 159 } 160 } else { 161 this.context.lineWidth = Constants.RULER_LINE_WIDTH; 162 } 163 if (Math.round(Math.abs(cur_num)) % Constants.NUMBER_10 == 0) { 164 this.drawIntegerLine(cur_x, cur_num); 165 } else { 166 if (!this.isVerticalScreen) { 167 this.context.moveTo((this.rulerWidth * Constants.NUMBER_9_5) / Constants.NUMBER_15, cur_x); 168 this.context.lineTo(this.rulerWidth * Constants.NUMBER_10_5 / Constants.NUMBER_15, cur_x); 169 } else { 170 this.context.moveTo(cur_x, (this.rulerWidth * Constants.NUMBER_9_5) / Constants.NUMBER_15); 171 this.context.lineTo(cur_x, this.rulerWidth * Constants.NUMBER_10_5 / Constants.NUMBER_15); 172 } 173 } 174 this.context.stroke(); 175 this.context.closePath(); 176 } 177 } 178 179 onTouchEvent(event: TouchEvent): void { 180 let axis = this.isVerticalScreen ? 'x' : 'y'; 181 if (event.type === TouchType.Down) { 182 this.startPos = event.touches[0][axis]; 183 this.previous = new Date().getTime(); 184 } 185 if (event.type !== TouchType.Move) { 186 return; 187 } 188 let now = new Date().getTime(); 189 if (now - this.previous < Constants.TIMEOUT) { 190 return; 191 } 192 this.previous = now; 193 let dir = this.startPos - event.touches[0][axis]; 194 if (Math.abs(dir / 5) < 1) { 195 return; 196 } 197 this.current_def += Number.parseInt((dir / 5).toFixed(0)); 198 this.startPos = event.touches[0][axis]; 199 if (Math.abs(this.current_def) > Constants.EDGE_ANGLE) { 200 this.current_def = this.current_def > Constants.EDGE_ANGLE ? Constants.EDGE_ANGLE : -Constants.EDGE_ANGLE; 201 } 202 this.drawRuler(); 203 this.broadCast.emit(Constants.RULER_CHANGED, [this.current_def]); 204 } 205 206 onResetClicked(): void { 207 this.current_def = Constants.NUMBER_0; 208 this.drawRuler(); 209 } 210 211 integerAngleToString(currentAngle: number): string | undefined{ 212 if (currentAngle % 10 === 0 && Math.abs(currentAngle) <= 40) { 213 return currentAngle.toString(); 214 } 215 216 return undefined; 217 } 218 219 aboutToAppear(): void { 220 this.resetClicked = (): void => this.onResetClicked(); 221 this.broadCast.on(Constants.CROP_RESET_CLICKED, this.resetClicked); 222 this.iniSize(); 223 } 224 225 drawRuler(): void { 226 this.context.clearRect(0, 0, this.cWidth, this.cHeight); 227 this.drawMidLine(); 228 this.drawLine(); 229 } 230 231 aboutToDisappear(): void { 232 this.broadCast.off(Constants.CROP_RESET_CLICKED, this.resetClicked); 233 } 234 235 build() { 236 Flex({ 237 direction: this.isVerticalScreen ? FlexDirection.Column : FlexDirection.Row, 238 alignItems: ItemAlign.Center, 239 justifyContent: FlexAlign.Center 240 }) { 241 Column() { 242 Canvas(this.context) 243 .onReady(() => { 244 this.drawRuler(); 245 }) 246 } 247 .onTouch((event?: TouchEvent) => { 248 this.onTouchEvent(event as TouchEvent); 249 }) 250 .width(this.isVerticalScreen ? this.rulerLength : Constants.CROP_RULER_WIDTH) 251 .height(this.isVerticalScreen ? this.rulerWidth : this.rulerLength) 252 } 253 } 254} 255