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