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