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