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