1/* 2 * Copyright (c) 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 { Dispatch, OhCombinedState, Unsubscribe } from '../../redux/store'; 17import { getStore } from '../../redux/store'; 18import { Action } from '../../redux/actions/Action'; 19import { EventBus } from '../../worker/eventbus/EventBus'; 20import { EventBusManager } from '../../worker/eventbus/EventBusManager'; 21import { CameraId } from '../../setting/settingitem/CameraId'; 22 23let SHOW_FOLD_CANVAS: number = 0 24let SHOW_NOT_TAKE_VIDEO_CANVAS: number = 1 25let SHOW_TAKING_VIDEO_CANVAS: number = 2 26 27class StateStruct { 28 mode: string = 'PHOTO'; 29 videoState: string = 'beforeTakeVideo'; 30 cameraPosition: CameraId = CameraId.BACK; 31 zoomRatio: number = 1; 32 isShowZoomText: boolean = false; 33 showZoomLabelValue: boolean = true; 34 minZoomRatio: number = 1; 35 maxZoomRatio: number = 6; 36} 37 38class ZoomViewDispatcher { 39 private mDispatch: Dispatch = (data) => data; 40 41 public setDispatch(dispatch: Dispatch) { 42 this.mDispatch = dispatch; 43 } 44 45 public updateZoomRatio(zoomRatio: number): void { 46 this.mDispatch(Action.changeZoomRatio(zoomRatio)); 47 } 48 49 public updateShowZoomFlag(flag: boolean): void { 50 this.mDispatch(Action.updateShowZoomTextFlag(flag)); 51 } 52 53 public updateShowZoomLabelValue(flag: boolean): void { 54 this.mDispatch(Action.updateShowZoomLabelValue(flag)); 55 } 56} 57 58class ZoomRatioStruct { 59 zoomRatio: number = 0; 60} 61 62class VideoStateStruct { 63 videoState: string = ''; 64} 65 66@Component 67export struct ZoomView { 68 private appEventBus: EventBus = EventBusManager.getInstance().getEventBus() 69 @State state: StateStruct = new StateStruct(); 70 @State offsetX: number = 0 71 @State triggerRebuildNum: number = 0 72 private mAction: ZoomViewDispatcher = new ZoomViewDispatcher(); 73 private notTakeVideoExtCanvasWidth: number = 360 74 private takingVideoExtCanvasWidth: number = 196 75 private foldCanvasWidth: number = 94 76 private canvasHeight: number = 82 77 private touchedOffsetX: number = this.takingVideoExtCanvasWidth / 2 78 private startOffsetX: number = 0 79 private canvasSettings: RenderingContextSettings = new RenderingContextSettings(true) 80 private notTakeVideoExtCanvasCtx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.canvasSettings) 81 private takingVideoExtCanvasCtx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.canvasSettings) 82 private foldCanvasCtx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.canvasSettings) 83 private notTakeVideoExtOffCanvasCtx: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D( 84 this.notTakeVideoExtCanvasWidth, this.canvasHeight, this.canvasSettings) 85 private takingVideoExtOffCanvasCxt: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D( 86 this.takingVideoExtCanvasWidth, this.canvasHeight, this.canvasSettings) 87 private foldOffCanvasCtx: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D( 88 this.foldCanvasWidth, this.canvasHeight, this.canvasSettings) 89 private lpgTimer: number = 0 90 private pgTimer: number = 0 91 private lpgExp: boolean = false 92 private pgExp: boolean = false 93 private baseZoomRatio: number = 1 94 private mainDotRadius: number = 1.5 95 private secDotRadius: number = 0.75 96 private centerDotRadius: number = 2.5 97 private dotSpacing: number = 4 98 99 aboutToAppear(): void { 100 getStore().subscribe((state: OhCombinedState) => { 101 this.state = { 102 mode: state.modeReducer.mode, 103 videoState: state.recordReducer.videoState, 104 cameraPosition: state.cameraReducer.cameraPosition, 105 zoomRatio: state.zoomReducer.zoomRatio, 106 isShowZoomText: state.zoomReducer.isShowZoomText, 107 showZoomLabelValue: state.zoomReducer.showZoomLabelValue, 108 minZoomRatio: state.zoomReducer.minZoomRatio, 109 maxZoomRatio: state.zoomReducer.maxZoomRatio 110 }; 111 }, (dispatch: Dispatch) => { 112 this.mAction.setDispatch(dispatch); 113 }); 114 this.appEventBus.on(Action.ACTION_CHANGE_ZOOM_RATIO, (data: ZoomRatioStruct) => this.updateZoomOffset(data)) 115 this.appEventBus.on(Action.ACTION_UPDATE_VIDEO_STATE, (data: VideoStateStruct) => this.updateZoomState(data)) 116 } 117 118 aboutToDisappear(): void { 119 this.appEventBus.off(Action.ACTION_CHANGE_ZOOM_RATIO, (data: ZoomRatioStruct) => this.updateZoomOffset(data)) 120 this.appEventBus.off(Action.ACTION_UPDATE_VIDEO_STATE, (data: VideoStateStruct) => this.updateZoomState(data)) 121 } 122 123 private getCurrentCanvasType(): number { 124 if (this.state.isShowZoomText && (this.state.videoState === 'beforeTakeVideo' 125 && (this.state.mode === 'PHOTO' || this.state.mode === 'VIDEO'))) { 126 return SHOW_NOT_TAKE_VIDEO_CANVAS 127 } else if (this.state.mode === 'VIDEO' 128 && (this.state.isShowZoomText || this.state.videoState !== 'beforeTakeVideo')) { 129 return SHOW_TAKING_VIDEO_CANVAS 130 } else { 131 return SHOW_FOLD_CANVAS 132 } 133 } 134 135 private lpgOnAction(): void { 136 this.clearTimer() 137 this.mAction.updateShowZoomFlag(true) 138 this.baseZoomRatio = this.state.zoomRatio 139 this.offsetX = (this.state.zoomRatio - 1) * this.getZoomOffsetUnit() 140 this.lpgExp = true 141 this.pgExp = false 142 this.triggerRebuildNum = this.triggerRebuildNum + 0.0001 143 } 144 145 private lpgOnActionEnd(): void { 146 if (this.lpgTimer) { 147 clearTimeout(this.lpgTimer) 148 } 149 this.lpgTimer = setTimeout(() => { 150 if (this.lpgExp && !this.pgExp) { 151 this.mAction.updateShowZoomFlag(false) 152 this.triggerRebuildNum = this.triggerRebuildNum + 0.0001 153 } 154 this.lpgExp = false 155 }, 3000) 156 } 157 158 private changeZoomRatioOnTakingVideoExt(): void { 159 if (this.touchedOffsetX > this.takingVideoExtCanvasWidth / 2) { 160 this.addZoomRatio() 161 } else if (this.touchedOffsetX < this.takingVideoExtCanvasWidth / 2) { 162 this.subtractZoomRatio() 163 } else { 164 this.triggerRebuildNum = this.triggerRebuildNum + 0.0001 165 this.mAction.updateShowZoomFlag(false) 166 } 167 } 168 169 private addZoomRatio(): void { 170 let curZoomRatio = this.state.zoomRatio + 0.1 171 if (curZoomRatio > this.state.maxZoomRatio) { 172 curZoomRatio = this.state.maxZoomRatio 173 } 174 this.mAction.updateZoomRatio(curZoomRatio) 175 this.mAction.updateShowZoomFlag(true) 176 this.triggerRebuildNum = this.triggerRebuildNum + 0.0001 177 } 178 179 private subtractZoomRatio(): void { 180 let curZoomRatio = this.state.zoomRatio - 0.1 181 if (curZoomRatio < this.state.minZoomRatio) { 182 curZoomRatio = this.state.minZoomRatio 183 } 184 this.mAction.updateZoomRatio(curZoomRatio) 185 this.mAction.updateShowZoomFlag(true) 186 this.triggerRebuildNum = this.triggerRebuildNum - 0.0001 187 } 188 189 private takingVideoExtTouched(event?: TouchEvent): void { 190 if (!event) { 191 return; 192 } 193 if (event.type === TouchType.Down) { 194 this.touchedOffsetX = event.touches[0].x 195 this.startOffsetX = event.touches[0].x 196 this.changeZoomRatioOnTakingVideoExt() 197 } 198 if (event.type === TouchType.Up) { 199 this.touchedOffsetX = this.takingVideoExtCanvasWidth / 2 200 this.changeZoomRatioOnTakingVideoExt() 201 } 202 } 203 204 private takingVideoExtLongPgAction(event?: GestureEvent): void { 205 if (!event) { 206 return; 207 } 208 this.touchedOffsetX = event.fingerList[0].localX 209 this.changeZoomRatioOnTakingVideoExt() 210 } 211 212 private takingVideoExtLongPgActionEnd(): void { 213 this.touchedOffsetX = this.takingVideoExtCanvasWidth / 2 214 this.changeZoomRatioOnTakingVideoExt() 215 } 216 217 private takingVideoExtPgActionStart(event?: GestureEvent): void { 218 if (!event) { 219 return; 220 } 221 this.touchedOffsetX = this.startOffsetX + event.offsetX 222 this.changeZoomRatioOnTakingVideoExt() 223 } 224 225 private takingVideoExtPgActionUpdate(event?: GestureEvent): void { 226 if (!event) { 227 return; 228 } 229 this.touchedOffsetX = this.startOffsetX + event.offsetX 230 let takingVideoExtMaxOffsetX = this.takingVideoExtCanvasWidth - this.getZoomBtnRadius() - this.secDotRadius 231 let takingVideoExtMinOffsetX = this.getZoomBtnRadius() + this.secDotRadius 232 if (this.touchedOffsetX > takingVideoExtMaxOffsetX) { 233 this.touchedOffsetX = takingVideoExtMaxOffsetX 234 } else if (this.touchedOffsetX < takingVideoExtMinOffsetX) { 235 this.touchedOffsetX = takingVideoExtMinOffsetX 236 } 237 this.changeZoomRatioOnTakingVideoExt() 238 } 239 240 private takingVideoExtPgActionEnd(event?: GestureEvent): void { 241 if (!event) { 242 return; 243 } 244 this.touchedOffsetX = this.takingVideoExtCanvasWidth / 2 245 this.startOffsetX = 0 246 this.changeZoomRatioOnTakingVideoExt() 247 } 248 249 private subtractTouched(event?: TouchEvent): void { 250 if (!event) { 251 return; 252 } 253 if (event.type === TouchType.Down) { 254 this.subtractZoomRatio() 255 } 256 if (event.type === TouchType.Up) { 257 this.mAction.updateShowZoomFlag(false) 258 } 259 } 260 261 private subtractLongOnAction(event?: GestureEvent): void { 262 if (!event) { 263 return; 264 } 265 this.subtractZoomRatio() 266 } 267 268 private subtractLongOnActionEnd(): void { 269 this.mAction.updateShowZoomFlag(false) 270 } 271 272 private addTouched(event?: TouchEvent): void { 273 if (!event) { 274 return; 275 } 276 if (event.type === TouchType.Down) { 277 this.addZoomRatio() 278 } 279 if (event.type === TouchType.Up) { 280 this.mAction.updateShowZoomFlag(false) 281 } 282 } 283 284 private addLongOnAction(): void { 285 this.addZoomRatio() 286 } 287 288 private addLongOnActionEnd(): void { 289 this.mAction.updateShowZoomFlag(false) 290 } 291 292 private pgOnActionStart(): void { 293 this.clearTimer() 294 this.mAction.updateShowZoomFlag(true) 295 this.mAction.updateShowZoomLabelValue(false) 296 this.baseZoomRatio = this.state.zoomRatio 297 this.pgExp = true 298 this.lpgExp = false 299 } 300 301 private pgOnActionUpdate(event?: GestureEvent): void { 302 if (!event) { 303 return; 304 } 305 this.offsetX = (this.baseZoomRatio - this.state.minZoomRatio) * this.getZoomOffsetUnit() + event.offsetX 306 this.updateZoomRatio() 307 } 308 309 private pgOnActionEnd(): void { 310 this.mAction.updateShowZoomLabelValue(true) 311 if (this.pgTimer) { 312 clearTimeout(this.pgTimer) 313 } 314 this.pgTimer = setTimeout(() => { 315 if (this.pgExp && !this.lpgExp) { 316 this.mAction.updateShowZoomFlag(false) 317 } 318 this.pgExp = false 319 }, 3000) 320 } 321 322 private mOnTouch(event: TouchEvent): void { 323 if (event.type === TouchType.Down) { 324 this.clearTimer() 325 this.mAction.updateShowZoomFlag(true) 326 this.pgExp = true 327 this.lpgExp = false 328 329 let x = event.touches[0].x 330 let zoomRatio = this.state.zoomRatio 331 if (this.state.videoState === 'beforeTakeVideo' && this.getCurrentCanvasType() === SHOW_NOT_TAKE_VIDEO_CANVAS) { 332 if (x < vp2px(36)) { 333 zoomRatio = this.state.minZoomRatio 334 } 335 if (x > this.notTakeVideoExtCanvasWidth - vp2px(36)) { 336 zoomRatio = this.state.maxZoomRatio 337 } 338 if (x > vp2px(36) && x < this.notTakeVideoExtCanvasWidth - vp2px(36)) { 339 this.offsetX = x - this.getPadding() 340 this.updateZoomRatio() 341 return; 342 } 343 } 344 this.offsetX = (zoomRatio - 1) * this.getZoomOffsetUnit() 345 this.updateZoomRatio() 346 } else if (event.type === TouchType.Up) { 347 if (this.pgTimer) { 348 clearTimeout(this.pgTimer) 349 } 350 this.pgTimer = setTimeout(() => { 351 if (this.pgExp && !this.lpgExp) { 352 this.mAction.updateShowZoomFlag(false) 353 } 354 this.pgExp = false 355 }, 3000) 356 } 357 358 } 359 360 private getZoomBtnCenterX(): number { 361 if (this.getCurrentCanvasType() === SHOW_TAKING_VIDEO_CANVAS) { 362 return this.touchedOffsetX 363 } 364 if (this.offsetX === 0 && this.state.zoomRatio !== 1) { 365 this.offsetX = (this.state.zoomRatio - this.state.minZoomRatio) * this.getZoomOffsetUnit() 366 } 367 if (this.state.zoomRatio === 1 && this.offsetX !== 0) { 368 this.offsetX = 0 369 } 370 let padding = this.getPadding() 371 let result = this.offsetX + padding + this.mainDotRadius 372 if (result > this.notTakeVideoExtCanvasWidth - padding - this.mainDotRadius) { 373 result = this.notTakeVideoExtCanvasWidth - padding - this.mainDotRadius 374 } 375 if (result < padding + this.mainDotRadius) { 376 result = padding + this.mainDotRadius 377 } 378 return result 379 } 380 381 private getZoomOffsetUnit(): number { 382 let padding = this.getPadding(); 383 let fullWidth = this.notTakeVideoExtCanvasWidth - padding * 2 - this.mainDotRadius * 2; 384 return fullWidth / (this.state.maxZoomRatio - this.state.minZoomRatio); 385 } 386 387 private updateZoomOffset(data: ZoomRatioStruct): void { 388 let offset = (data.zoomRatio - this.state.minZoomRatio) * this.getZoomOffsetUnit(); 389 this.offsetX = offset; 390 } 391 392 private updateZoomState(data: VideoStateStruct): void { 393 if (data.videoState === 'beforeTakeVideo') { 394 this.clearTimer(); 395 this.mAction.updateShowZoomFlag(false); 396 this.pgExp = false; 397 } 398 } 399 400 private clearTimer(): void { 401 if (this.pgTimer) { 402 clearTimeout(this.pgTimer); 403 } 404 if (this.lpgTimer) { 405 clearTimeout(this.lpgTimer); 406 } 407 } 408 409 private updateZoomRatio(): void { 410 let padding = this.getPadding() 411 let fullWidth = this.notTakeVideoExtCanvasWidth - padding * 2 - this.mainDotRadius * 2 412 let curZoomRatio = (this.offsetX / fullWidth) * (this.state.maxZoomRatio - this.state.minZoomRatio) + this.state.minZoomRatio 413 if (curZoomRatio > this.state.maxZoomRatio) { 414 curZoomRatio = this.state.maxZoomRatio 415 } 416 if (curZoomRatio < this.state.minZoomRatio) { 417 curZoomRatio = this.state.minZoomRatio 418 } 419 this.mAction.updateZoomRatio(curZoomRatio) 420 } 421 422 private getPadding(): number { 423 if (this.getCurrentCanvasType() === SHOW_NOT_TAKE_VIDEO_CANVAS) { 424 return 32 425 } else if (this.getCurrentCanvasType() === SHOW_TAKING_VIDEO_CANVAS) { 426 return 15.5 427 } else { 428 return 32 429 } 430 } 431 432 private getZoomText() { 433 return `${Number(this.state.zoomRatio.toFixed(1))}x` 434 } 435 436 private getZoomBtnRadius(): number { 437 if (!this.state.showZoomLabelValue) { 438 return 17.25 439 } else { 440 return 15.25 441 } 442 } 443 444 build() { 445 Stack({ alignContent: Alignment.Top }) { 446 Stack({ alignContent: Alignment.Top }) 447 .width(this.offsetX + this.touchedOffsetX + this.state.zoomRatio) 448 .height(this.triggerRebuildNum) 449 .visibility(Visibility.None) 450 if (this.getCurrentCanvasType() === SHOW_NOT_TAKE_VIDEO_CANVAS) { 451 Canvas(this.notTakeVideoExtCanvasCtx) 452 .width(this.notTakeVideoExtCanvasWidth) 453 .height(this.canvasHeight) 454 .onReady(() => { 455 this.notTakeVideoExtCanvasCtx.clearRect(0, 0, this.notTakeVideoExtCanvasWidth, this.canvasHeight) 456 this.notTakeVideoExtOffCanvasCtx.clearRect(0, 0, this.notTakeVideoExtCanvasWidth, this.canvasHeight) 457 this.notTakeVideoExtOffCanvasCtx.strokeStyle = '#ffffff' 458 this.notTakeVideoExtOffCanvasCtx.fillStyle = '#ffffff' 459 this.notTakeVideoExtOffCanvasCtx.lineWidth = 1.5 460 this.notTakeVideoExtOffCanvasCtx.beginPath() 461 this.notTakeVideoExtOffCanvasCtx.arc(this.getZoomBtnCenterX(), this.canvasHeight / 2, this.getZoomBtnRadius(), 0, 6.28) 462 this.notTakeVideoExtOffCanvasCtx.stroke() 463 if (this.state.showZoomLabelValue) { 464 this.notTakeVideoExtOffCanvasCtx.font = `bold ${vp2px(11)}px` 465 this.notTakeVideoExtOffCanvasCtx.textAlign = 'center' 466 this.notTakeVideoExtOffCanvasCtx.fillText(this.getZoomText(), this.getZoomBtnCenterX(), this.canvasHeight / 2 + 5) 467 } else { 468 this.notTakeVideoExtOffCanvasCtx.beginPath() 469 this.notTakeVideoExtOffCanvasCtx.arc(this.getZoomBtnCenterX(), this.canvasHeight / 2, this.centerDotRadius, 0, 6.28) 470 this.notTakeVideoExtOffCanvasCtx.fill() 471 } 472 473 let spotCount = (this.notTakeVideoExtCanvasWidth - this.getPadding() * 2 - this.mainDotRadius * 4 - this.dotSpacing) / (this.dotSpacing + this.secDotRadius * 2) + 2 474 for (let i = 0; i < spotCount; i++) { 475 let spotCenter = 0 476 let spotRadius = 0 477 if (i === 0) { 478 spotRadius = this.mainDotRadius 479 spotCenter = this.getPadding() + spotRadius 480 this.notTakeVideoExtOffCanvasCtx.font = `bold ${vp2px(11)}px` 481 this.notTakeVideoExtOffCanvasCtx.textAlign = 'center' 482 this.notTakeVideoExtOffCanvasCtx.fillText(`${this.state.minZoomRatio}x`, spotCenter, this.canvasHeight / 2 - (!this.state.showZoomLabelValue ? 26 : 24)) 483 } else if (i === spotCount - 1) { 484 spotRadius = this.mainDotRadius 485 spotCenter = this.notTakeVideoExtCanvasWidth - this.getPadding() - spotRadius 486 this.notTakeVideoExtOffCanvasCtx.font = `bold ${vp2px(11)}px` 487 this.notTakeVideoExtOffCanvasCtx.textAlign = 'center' 488 this.notTakeVideoExtOffCanvasCtx.fillText(`${this.state.maxZoomRatio}x`, spotCenter, this.canvasHeight / 2 - (!this.state.showZoomLabelValue ? 26 : 24)) 489 } else { 490 spotRadius = this.secDotRadius 491 spotCenter = this.getPadding() + this.mainDotRadius + (2 * i - 1) * this.secDotRadius + i * this.dotSpacing 492 this.notTakeVideoExtOffCanvasCtx.globalAlpha = 0.2 493 } 494 if (spotCenter < this.getZoomBtnCenterX() - this.getZoomBtnRadius() || spotCenter > this.getZoomBtnCenterX() + this.getZoomBtnRadius()) { 495 this.notTakeVideoExtOffCanvasCtx.beginPath() 496 this.notTakeVideoExtOffCanvasCtx.arc(spotCenter, this.canvasHeight / 2, spotRadius, 0, 6.28) 497 this.notTakeVideoExtOffCanvasCtx.fill() 498 } 499 this.notTakeVideoExtOffCanvasCtx.globalAlpha = 1 500 } 501 this.notTakeVideoExtCanvasCtx.transferFromImageBitmap(this.notTakeVideoExtOffCanvasCtx.transferToImageBitmap()) 502 }) 503 .gesture(GestureGroup(GestureMode.Parallel, 504 PanGesture({ fingers: 1, distance: 1, direction: PanDirection.Horizontal }) 505 .onActionStart(() => this.pgOnActionStart()) 506 .onActionUpdate((event?: GestureEvent) => { 507 if (event) { 508 return this.pgOnActionUpdate(event); 509 } 510 }) 511 .onActionEnd(() => this.pgOnActionEnd()))) 512 .onTouch((event?: TouchEvent) => { 513 if (event) { 514 return this.mOnTouch(event); 515 } 516 }) 517 } else if (this.getCurrentCanvasType() === SHOW_TAKING_VIDEO_CANVAS) { 518 Row() { 519 Image($r('app.media.ic_camera_public_focus_ev_bright_subtract')) 520 .width(24) 521 .height(24) 522 .fillColor(Color.White) 523 .onTouch((event?: TouchEvent) => this.subtractTouched(event)) 524 .gesture( 525 GestureGroup( 526 GestureMode.Parallel, 527 LongPressGesture({ repeat: true }) 528 .onAction((event?: GestureEvent) => this.subtractLongOnAction(event)) 529 .onActionEnd(() => this.subtractLongOnActionEnd()), 530 ) 531 ) 532 Canvas(this.takingVideoExtCanvasCtx) 533 .width(this.takingVideoExtCanvasWidth) 534 .height(this.canvasHeight) 535 .onReady(() => { 536 this.takingVideoExtCanvasCtx.clearRect(0, 0, this.takingVideoExtCanvasWidth, this.canvasHeight) 537 this.takingVideoExtOffCanvasCxt.clearRect(0, 0, this.takingVideoExtCanvasWidth, this.canvasHeight) 538 this.takingVideoExtOffCanvasCxt.strokeStyle = '#ffffff' 539 this.takingVideoExtOffCanvasCxt.fillStyle = '#ffffff' 540 this.takingVideoExtOffCanvasCxt.lineWidth = 1.5 541 this.takingVideoExtOffCanvasCxt.beginPath() 542 this.takingVideoExtOffCanvasCxt.arc(this.getZoomBtnCenterX(), this.canvasHeight / 2, this.getZoomBtnRadius(), 0, 6.28) 543 this.takingVideoExtOffCanvasCxt.stroke() 544 if (this.state.isShowZoomText) { 545 this.takingVideoExtOffCanvasCxt.beginPath() 546 this.takingVideoExtOffCanvasCxt.arc(this.getZoomBtnCenterX(), this.canvasHeight / 2, this.centerDotRadius, 0, 6.28) 547 this.takingVideoExtOffCanvasCxt.fill() 548 } else { 549 this.takingVideoExtOffCanvasCxt.font = `bold ${vp2px(11)}px` 550 this.takingVideoExtOffCanvasCxt.textAlign = 'center' 551 this.takingVideoExtOffCanvasCxt.fillText(this.getZoomText(), this.getZoomBtnCenterX(), this.canvasHeight / 2 + 5) 552 } 553 554 let spotCount = 30 555 for (let i = 0; i < spotCount; i++) { 556 let spotCenter = 0 557 let spotRadius = 0 558 spotRadius = this.secDotRadius 559 spotCenter = this.getPadding() + (2 * i + 1) * this.secDotRadius + i * this.dotSpacing 560 this.takingVideoExtOffCanvasCxt.globalAlpha = 0.2 561 if (spotCenter < this.getZoomBtnCenterX() - this.getZoomBtnRadius() || spotCenter > this.getZoomBtnCenterX() + this.getZoomBtnRadius()) { 562 this.takingVideoExtOffCanvasCxt.beginPath() 563 this.takingVideoExtOffCanvasCxt.arc(spotCenter, this.canvasHeight / 2, spotRadius, 0, 6.28) 564 this.takingVideoExtOffCanvasCxt.fill() 565 } 566 this.takingVideoExtOffCanvasCxt.globalAlpha = 1 567 } 568 569 this.takingVideoExtCanvasCtx.transferFromImageBitmap(this.takingVideoExtOffCanvasCxt.transferToImageBitmap()) 570 }) 571 .gesture( 572 GestureGroup( 573 GestureMode.Parallel, 574 LongPressGesture({ repeat: true }) 575 .onAction((event?: GestureEvent) => this.takingVideoExtLongPgAction(event)) 576 .onActionEnd(() => this.takingVideoExtLongPgActionEnd()), 577 PanGesture({ fingers: 1, distance: 1, direction: PanDirection.Horizontal }) 578 .onActionStart((event?: GestureEvent) => this.takingVideoExtPgActionStart(event)) 579 .onActionUpdate((event?: GestureEvent) => this.takingVideoExtPgActionUpdate(event)) 580 .onActionEnd((event?: GestureEvent) => this.takingVideoExtPgActionEnd(event)) 581 )) 582 .onTouch((event?: TouchEvent) => this.takingVideoExtTouched(event)) 583 Image($r('app.media.ic_camera_public_focus_ev_bright_add')) 584 .width(24) 585 .height(24) 586 .fillColor(Color.White) 587 .onTouch((event?: TouchEvent) => this.addTouched(event)) 588 .gesture( 589 GestureGroup( 590 GestureMode.Parallel, 591 LongPressGesture({ repeat: true }) 592 .onAction(() => this.addLongOnAction()) 593 .onActionEnd(() => this.addLongOnActionEnd()), 594 ) 595 ) 596 }.width(this.notTakeVideoExtCanvasWidth).height('100%').padding({ left: 58, right: 58 }) 597 } else { 598 Canvas(this.foldCanvasCtx) 599 .width(this.foldCanvasWidth) 600 .height(this.canvasHeight) 601 .onReady(() => { 602 this.foldCanvasCtx.clearRect(0, 0, this.foldCanvasWidth, this.canvasHeight) 603 this.foldOffCanvasCtx.clearRect(0, 0, this.foldCanvasWidth, this.canvasHeight) 604 this.foldOffCanvasCtx.strokeStyle = '#ffffff' 605 this.foldOffCanvasCtx.fillStyle = '#ffffff' 606 this.foldOffCanvasCtx.lineWidth = 1.5 607 this.foldOffCanvasCtx.beginPath() 608 this.foldOffCanvasCtx.arc(this.foldCanvasWidth / 2, this.canvasHeight / 2, this.getZoomBtnRadius(), 0, 6.28) 609 this.foldOffCanvasCtx.stroke() 610 this.foldOffCanvasCtx.font = `bold ${vp2px(10)}px` 611 this.foldOffCanvasCtx.textAlign = 'center' 612 this.foldOffCanvasCtx.fillText(this.getZoomText(), this.foldCanvasWidth / 2, this.canvasHeight / 2 + 3) 613 614 let fullWidth = this.foldCanvasWidth / 2 - this.mainDotRadius 615 let spotCount = (fullWidth - this.mainDotRadius * 2 - this.dotSpacing) / (this.dotSpacing + this.secDotRadius * 2) + 2 616 let spotOffset = this.state.zoomRatio === this.state.maxZoomRatio ? this.foldCanvasWidth / 2 - fullWidth 617 : this.foldCanvasWidth / 2 618 for (let i = 0; i < spotCount; i++) { 619 let spotCenter = 0 620 let spotRadius = 0 621 if (i === 0) { 622 spotRadius = this.mainDotRadius 623 spotCenter = spotOffset + spotRadius 624 } else if (i === spotCount - 1) { 625 spotRadius = this.mainDotRadius 626 spotCenter = spotOffset + this.mainDotRadius * 2 + (i - 1) * this.dotSpacing + (2 * i - 1) * this.secDotRadius - this.secDotRadius + spotRadius 627 } else { 628 spotRadius = this.secDotRadius 629 spotCenter = spotOffset + this.mainDotRadius * 2 + (i - 1) * this.dotSpacing + (2 * i - 1) * this.secDotRadius + spotRadius 630 this.foldOffCanvasCtx.globalAlpha = 0.2 631 } 632 if (spotCenter < this.foldCanvasWidth / 2 - this.getZoomBtnRadius() || spotCenter > this.foldCanvasWidth / 2 + this.getZoomBtnRadius()) { 633 this.foldOffCanvasCtx.beginPath() 634 this.foldOffCanvasCtx.arc(spotCenter, this.canvasHeight / 2, spotRadius, 0, 6.28) 635 this.foldOffCanvasCtx.fill() 636 } 637 this.foldOffCanvasCtx.globalAlpha = 1.0 638 } 639 640 this.foldCanvasCtx.transferFromImageBitmap(this.foldOffCanvasCtx.transferToImageBitmap()) 641 }) 642 .gesture( 643 GestureGroup( 644 GestureMode.Parallel, 645 LongPressGesture({ repeat: true }) 646 .onAction(() => this.lpgOnAction()) 647 .onActionEnd(() => this.lpgOnActionEnd()), 648 PanGesture({ fingers: 1, distance: 1, direction: PanDirection.Horizontal }) 649 .onActionStart(() => this.pgOnActionStart()) 650 .onActionUpdate((event?: GestureEvent) => this.pgOnActionUpdate(event)) 651 .onActionEnd(() => this.pgOnActionEnd()) 652 ) 653 ) 654 } 655 }.width('100%').height(this.canvasHeight).margin({ bottom: !this.state.showZoomLabelValue ? 58 : 0 }) 656 } 657}