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