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