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