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