1/* 2 * Copyright (c) 2023-2024 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 router from '@system.router'; 17import display from '@ohos.display'; 18import deviceInfo from '@ohos.deviceInfo'; 19import { Action, UiStateMode } from '@ohos/common/src/main/ets/default/redux/actions/Action'; 20import { AssistiveGridView } from '@ohos/common/src/main/ets/default/featurecommon/assistivegridview/AssistiveGridView'; 21import { BigText } from '@ohos/common/src/main/ets/default/featurecommon/bigtext/BigText'; 22import { CameraNeedStatus, CameraStatus } from '@ohos/common/src/main/ets/default/utils/Constants'; 23import { CameraId } from '@ohos/common/src/main/ets/default/setting/settingitem/CameraId'; 24import { EventBus } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBus'; 25import { EventBusManager } from '@ohos/common/src/main/ets/default/worker/eventbus/EventBusManager'; 26import { Dispatch, OhCombinedState } from '@ohos/common/src/main/ets/default/redux/store'; 27import { getStore } from '@ohos/common/src/main/ets/default/redux/store'; 28import { Log } from '@ohos/common/src/main/ets/default/utils/Log'; 29import { GeoLocation } from '@ohos/common/src/main/ets/default/featurecommon/geolocation/GeoLocation'; 30import { SettingManager } from '@ohos/common/src/main/ets/default/setting/SettingManager'; 31import { ShowFlashBlack } from '@ohos/common/src/main/ets/default/featurecommon/animate/ShowFlashBlack'; 32import { TimeLapseView } from '@ohos/common/src/main/ets/default/featurecommon/timelapseview/TimeLapseView'; 33import { ZoomText } from '@ohos/common/src/main/ets/default/featurecommon/zoomview/ZoomText'; 34import { BigVideoTimer } from './BigVideoTimer'; 35import { SmallVideoTimer } from './SmallVideoTimer'; 36import promptAction from '@ohos.promptAction'; 37import wantConstant from '@ohos.ability.wantConstant'; 38import { CameraPlatformCapability } from '@ohos/common/src/main/ets/default/camera/CameraPlatformCapability'; 39import { BusinessError } from '@ohos.base'; 40import { GlobalContext } from '@ohos/common/src/main/ets/default/utils/GlobalContext'; 41 42GlobalContext.get().setXComponentController(new XComponentController()) 43 44class StateStruct { 45 mode: string = 'PHOTO'; 46 curMode: string = 'PHOTO'; 47 isShowPreview: boolean = true; 48 surfaceId: number = 0; 49 xComponentWidth: number = 0; 50 xComponentHeight: number = 0; 51 cameraPosition: CameraId = CameraId.BACK; 52 curCameraPosition: CameraId = CameraId.BACK; 53 minZoomRatio: number = 1; 54 maxZoomRatio: number = 6; 55 zoomRatio: number = 0; 56 platformCapability: CameraPlatformCapability | undefined = undefined; 57 videoState: string = ''; 58 footBarHeight: number = 0; 59 isShowZoomText: boolean = false; 60 showZoomLabelValue: boolean = true; 61 modeIndex: number = 0; 62 isThirdPartyCall: boolean = false; 63 isShowBigText: boolean = false; 64 isShowtimeLapse: boolean = false; 65 isBigVideoTimerVisible: boolean = false; 66 isSmallVideoTimerVisible: boolean = false; 67 isAssGridViewShow: string = ''; 68 isShowFlashBlack: boolean = false; 69 modeChangeDone: boolean = false; 70 isShowPageView: boolean = false; 71 showBlur: boolean = false; 72 isFaCall: boolean = false; 73 rotateAngle: number = 0; 74 rotateAngleSec: number = 0; 75 switchBackgroundOpacity: number = 1; 76} 77 78class PreviewAreaDispatcher { 79 private mDispatch: Dispatch = (data) => data; 80 81 public setDispatch(dispatch: Dispatch) { 82 this.mDispatch = dispatch; 83 } 84 85 public initCamera(cameraId: CameraId, mode: string): void { 86 this.mDispatch(Action.initCamera(cameraId, mode)); 87 } 88 89 public initZoomRatio(min: number, max: number): void { 90 this.mDispatch(Action.initZoomRatio(min, max)); 91 } 92 93 public resetZoomRatio(zoomRatio: number): void { 94 this.mDispatch(Action.resetZoomRatio(zoomRatio)); 95 } 96 97 public changeZoomRatio(zoomRatio: number): void { 98 this.mDispatch(Action.changeZoomRatio(zoomRatio)); 99 } 100 101 public updateZoomPercentage(zoomPercentage: number): void { 102 this.mDispatch(Action.updateZoomPercentage(zoomPercentage)); 103 } 104 105 public prepareSurface(surfaceId: number): void { 106 this.mDispatch(Action.prepareSurface(surfaceId)); 107 } 108 109 public updateSurfaceId(surfaceId: number): void { 110 this.mDispatch(Action.updateSurfaceId(surfaceId)); 111 } 112 113 public startPreview(): void { 114 this.mDispatch(Action.startPreview()); 115 } 116 117 public switchCamera(cameraId: string): void { 118 this.mDispatch(Action.switchCamera(cameraId)); 119 } 120 121 public startVideoFlag(isStartVideo: boolean): void { 122 this.mDispatch(Action.startVideoFlag(isStartVideo)); 123 } 124 125 public updateCameraPosition(cameraPosition: string): void { 126 this.mDispatch(Action.updateCameraPosition(cameraPosition)); 127 } 128 129 public changeXComponentSize(xComponentWidth: number, xComponentHeight: number): void { 130 this.mDispatch(Action.changeXComponentSize(xComponentWidth, xComponentHeight)); 131 } 132 133 public updateShowPreviewFlag(isShowPreview: boolean): void { 134 this.mDispatch(Action.updateShowPreviewFlag(isShowPreview)); 135 } 136 137 public updateIsShowZoomText(isShowZoomText: boolean): void { 138 this.mDispatch(Action.updateShowZoomTextFlag(isShowZoomText)); 139 } 140 141 public updateIsPhotoZoomDetails(isPhotoZoomDetails: boolean): void { 142 this.mDispatch(Action.updatePhotoZoomDetailsFlag(isPhotoZoomDetails)); 143 } 144 145 public updateBaseZoom(zoomRatio: number): void { 146 this.mDispatch(Action.updateBaseZoom(zoomRatio)); 147 } 148 149 public changeImageSize(imageSize: SizeStruct): void { 150 this.mDispatch(Action.changeImageSize(imageSize)); 151 } 152 153 public changeVideoSize(videoSize: SizeStruct): void { 154 this.mDispatch(Action.changeVideoSize(videoSize)); 155 } 156 157 public close(): void { 158 this.mDispatch(Action.close()); 159 } 160 161 public stopRecording(): void { 162 this.mDispatch(Action.stopRecording()); 163 this.mDispatch(Action.updateVideoState('beforeTakeVideo')); 164 this.mDispatch(Action.updateBigVideoTimerVisible(false)); 165 this.mDispatch(Action.updateSmallVideoTimerVisible(false)); 166 this.mDispatch(Action.updateScreenStatus(false)); 167 } 168 169 public changeTimeLapse(isShowtimeLapse: boolean): void { 170 this.mDispatch(Action.changeTimeLapse(isShowtimeLapse)); 171 } 172 173 public capture(): void { 174 this.mDispatch(Action.updateShowFlashBlackFlag(true)); 175 this.mDispatch(Action.capture()); 176 } 177 178 public startRecording(): void { 179 this.mDispatch(Action.startRecording()); 180 this.mDispatch(Action.updateVideoState('startTakeVideo')); 181 this.mDispatch(Action.updateBigVideoTimerVisible(true)); 182 this.mDispatch(Action.updateScreenStatus(true)); 183 } 184 185 public assistiveGridView(isViewShow: number): void { 186 this.mDispatch(Action.assistiveGridView(isViewShow)); 187 } 188 189 public thirdPartyCall(isThirdPartyCall: boolean, thirdCallAction: string): void { 190 this.mDispatch(Action.thirdPartyCall(isThirdPartyCall, thirdCallAction)); 191 } 192 193 public faCall(isFaCall: boolean): void { 194 this.mDispatch(Action.faCall(isFaCall)); 195 } 196 197 public initMode(mode: string): void { 198 this.mDispatch(Action.initMode(mode)); 199 } 200 201 public updateModeIndex(index: number): void { 202 this.mDispatch(Action.updateModeIndex(index)); 203 } 204 205 public updateMode(mode: string): void { 206 this.mDispatch(Action.updateMode(mode)); 207 } 208 209 public changeToMode(mode: string): void { 210 this.mDispatch(Action.changeMode(mode)); 211 } 212 213 public swipeChangeMode(swipeModeIndex: number): void { 214 this.mDispatch(Action.swipeChangeMode(swipeModeIndex)); 215 } 216 217 public updateShowZoomLabelValue(flag: boolean): void { 218 this.mDispatch(Action.updateShowZoomLabelValue(flag)); 219 } 220 221 public reloadThumbnail(): void { 222 this.mDispatch(Action.reloadThumbnail()); 223 } 224 225 public changeCameraPosition(cameraPosition: string): void { 226 this.mDispatch(Action.setCameraPosition(cameraPosition)); 227 } 228 229 public updateShowPinch(flag: boolean): void { 230 this.mDispatch(Action.updateShowPinch(flag)); 231 } 232 233 public swipeModeChangeDone(actionOff: boolean): void { 234 this.mDispatch(Action.swipeModeChangeDone(actionOff)); 235 } 236} 237 238class SizeStruct { 239 width: number = 0; 240 height: number = 0; 241} 242 243class CameraInitStruct { 244 platformCapability: CameraPlatformCapability | undefined = undefined; 245} 246 247class ModeStruct { 248 mode: string = ''; 249} 250 251class KeepScreenOnStruct { 252 isKeepScreenOn: boolean = false; 253} 254 255@Component 256export struct PreviewArea { 257 private TAG: string = '[PreviewArea]:'; 258 appEventBus: EventBus = EventBusManager.getInstance().getEventBus(); 259 @State state: StateStruct = new StateStruct(); 260 @State mAspectRatio: number = 3 / 4; 261 @State btnSwitch: boolean = false; 262 @State btnSwitchSec: boolean = false; 263 @State isSwitchBackground: boolean = false; 264 @State pageType: string = ''; 265 private isShowPreview: boolean = false; 266 private isForegroundInit: boolean = false; 267 private settingManager = SettingManager.getInstance(); 268 private pinchGestureTimer: number = 0; 269 private baseZoom: number = 0; 270 private modeArray: Array<string> = ['PHOTO', 'VIDEO']; 271 private mAction: PreviewAreaDispatcher = new PreviewAreaDispatcher(); 272 273 private async onCameraInit(data: CameraInitStruct): Promise<void> { 274 Log.info(`${this.TAG} EventBus onCameraInit isShowPreview = ${this.isShowPreview} platformCapability = ${this.state.platformCapability} E`); 275 if (this.isForegroundInit === true) { 276 Log.info(`${this.TAG} EventBus onCameraInit foregroundInit`); 277 this.doCameraAction(); 278 if (!this.state.isThirdPartyCall) { 279 this.mAction.reloadThumbnail(); 280 } 281 this.isForegroundInit = false; 282 } 283 if (this.state.platformCapability) { 284 this.settingManager.loadAllSetting().then(() => { 285 this.settingManager.setCameraId(this.state.cameraPosition); 286 287 let imageSize = this.settingManager.getImageSize(); 288 this.mAction.changeImageSize(imageSize); 289 290 let videoSize = this.settingManager.getVideoSize(); 291 this.mAction.changeVideoSize(videoSize); 292 293 let isAssGridViewShow: number = Number(this.settingManager.getAssistiveGrid()); 294 this.mAction.assistiveGridView(isAssGridViewShow); 295 display.getDefaultDisplay().then((dis) => { 296 let screenHeight = px2vp(dis.height - 176); 297 let screenWidth = px2vp(dis.width); 298 299 this.settingManager.setScreenHeight(screenHeight); 300 this.settingManager.setScreenWidth(screenWidth); 301 302 let xComponentSize = this.settingManager.getPreviewDisplaySize(this.state.mode); 303 Log.info(this.TAG + " PreviewArea xComponentSize = " + JSON.stringify(xComponentSize)); 304 this.mAction.changeXComponentSize(xComponentSize.width, xComponentSize.height); 305 this.mAction.updateShowPreviewFlag(true); 306 }) 307 }) 308 } 309 Log.info(`${this.TAG} onCameraInit isShowPreview = ${this.state.isShowPreview} X`); 310 } 311 312 private async doCameraAction() { 313 Log.info(`${this.TAG} doCameraAction E`); 314 this.settingManager.setCameraId(this.state.cameraPosition); 315 if (this.state.curCameraPosition != this.state.cameraPosition) { 316 this.mAction.switchCamera(this.state.cameraPosition); 317 } else if (this.state.curMode != this.state.mode) { 318 this.mAction.changeToMode(this.state.mode); 319 } else { 320 this.mAction.startPreview(); 321 } 322 this.mAction.updateCameraPosition(this.state.cameraPosition); 323 this.mAction.updateMode(this.state.mode); 324 if (GlobalContext.get().getT<boolean>('keepCameraZoomRatio') && GlobalContext.get() 325 .getT<boolean>('keepCameraZoomRatio')) { 326 GlobalContext.get().setObject('keepCameraZoomRatio', false) 327 } else { 328 this.mAction.changeZoomRatio(1); 329 } 330 Log.info(`${this.TAG} doCameraAction X`); 331 } 332 333 private async onModeChanged(data: ModeStruct): Promise<void> { 334 Log.info(`${this.TAG} onModeChanged E data.mode: ${data.mode}`); 335 let xComponentSize = this.settingManager.getPreviewDisplaySize(data.mode); 336 this.mAction.changeXComponentSize(xComponentSize.width, xComponentSize.height); 337 this.mAction.updateShowPreviewFlag(true); 338 Log.info(`${this.TAG} onModeChanged X`); 339 } 340 341 private async onRecordError(): Promise<void> { 342 Log.info(`${this.TAG} onRecordError invoke E`); 343 promptAction.showToast({ 344 message: "录像异常", 345 duration: 2000, 346 }); 347 if (this.state.videoState === 'startTakeVideo') { 348 this.mAction.stopRecording(); 349 } 350 this.mAction.close(); 351 Log.info(`${this.TAG} onRecordError invoke X`); 352 } 353 354 aboutToAppear(): void { 355 Log.info(`${this.TAG} PreviewArea aboutToAppear ${JSON.stringify(router.getParams())}`); 356 let routerParams = router.getParams(); 357 if (routerParams && routerParams.pageType) { 358 this.pageType = routerParams.pageType.toString(); 359 } 360 361 getStore().subscribe((state: OhCombinedState) => { 362 let isShowBlur: boolean = !state.contextReducer.uiEnable && state.contextReducer.uiStateMode == UiStateMode.NONE; 363 this.state = { 364 mode: state.modeReducer.mode, 365 curMode: state.modeReducer.curMode, 366 isShowPreview: state.previewReducer.isShowPreview, 367 surfaceId: state.previewReducer.surfaceId, 368 xComponentWidth: state.previewReducer.xComponentWidth, 369 xComponentHeight: state.previewReducer.xComponentHeight, 370 cameraPosition: state.cameraReducer.cameraPosition, 371 curCameraPosition: state.cameraReducer.curCameraPosition, 372 minZoomRatio: state.zoomReducer.minZoomRatio, 373 maxZoomRatio: state.zoomReducer.maxZoomRatio, 374 zoomRatio: state.zoomReducer.zoomRatio, 375 platformCapability: state.cameraInitReducer.platformCapability, 376 videoState: state.recordReducer.videoState, 377 isShowZoomText: state.zoomReducer.isShowZoomText, 378 showZoomLabelValue: state.zoomReducer.showZoomLabelValue, 379 footBarHeight: state.contextReducer.footBarHeight, 380 isShowFlashBlack: state.previewReducer.isShowFlashBlack, 381 isShowBigText: state.modeReducer.isShowBigText, 382 isShowtimeLapse: state.settingReducer.isShowtimeLapse, 383 isBigVideoTimerVisible: state.recordReducer.isBigVideoTimerVisible, 384 isSmallVideoTimerVisible: state.recordReducer.isSmallVideoTimerVisible, 385 isAssGridViewShow: state.settingReducer.isAssGridViewShow, 386 modeIndex: state.modeReducer.modeIndex, 387 isThirdPartyCall: state.contextReducer.isThirdPartyCall, 388 modeChangeDone: state.modeReducer.modeChangeDone, 389 isShowPageView: state.settingReducer.isShowSettingView, 390 showBlur: isShowBlur, 391 isFaCall: state.contextReducer.isFaCall, 392 rotateAngle: 0, 393 rotateAngleSec: 0, 394 switchBackgroundOpacity: 1, 395 }; 396 }, (dispatch: Dispatch) => { 397 this.mAction.setDispatch(dispatch); 398 }); 399 this.state.platformCapability; 400 this.appEventBus.on(Action.ACTION_INIT_DONE, (data: CameraInitStruct) => this.onCameraInit(data)); 401 this.appEventBus.on(Action.ACTION_ON_MODE_CHANGED, (data: ModeStruct) => this.onModeChanged(data)); 402 this.appEventBus.on(Action.ACTION_KEEP_SCREEN_ON, (data: KeepScreenOnStruct) => this.onKeepScreen(data)); 403 this.appEventBus.on(Action.ACTION_RECORD_ERROR, () => this.onRecordError()); 404 this.appEventBus.on(Action.ACTION_UPDATE_CAMERA_STATUS, () => this.updateCameraStatus()); 405 GlobalContext.get().setObject('updateCameraStatus', () => { 406 Log.info(`${this.TAG} globalThis.updateCameraStatus called`); 407 this.updateCameraStatus(); 408 }); 409 this.calledByOther(); 410 this.mAction.initCamera(this.state.curCameraPosition, this.state.mode); 411 this.mAction.initZoomRatio(1, 6); //TODO 需要动态取得实际变焦能力范围 412 Log.start(Log.X_COMPONENT_LIFE); 413 } 414 415 aboutToDisappear(): void { 416 Log.info(`${this.TAG} previewAreaLand aboutToDisappear called`); 417 this.appEventBus.off(Action.ACTION_INIT_DONE, (data: CameraInitStruct) => this.onCameraInit(data)); 418 this.appEventBus.off(Action.ACTION_ON_MODE_CHANGED, (data: ModeStruct) => this.onModeChanged(data)); 419 this.appEventBus.off(Action.ACTION_UPDATE_CAMERA_STATUS, () => this.updateCameraStatus()); 420 GeoLocation.getInstance().off(); 421 GlobalContext.get().setObject('cameraNeedStatus', CameraNeedStatus.CAMERA_NEED_RELEASE); 422 this.updateCameraStatus(); 423 } 424 425 private releaseCamera(): void { 426 Log.info(`${this.TAG} globalThis.releaseCamera called`); 427 GlobalContext.get().setObject('cameraNeedStatus', CameraNeedStatus.CAMERA_NO_NEED_TO_DO); 428 if (this.state.videoState === 'startTakeVideo') { 429 this.mAction.stopRecording(); 430 } 431 this.mAction.close(); 432 } 433 434 private async onForegroundInit() { 435 Log.info(`${this.TAG} onForegroundInit E `); 436 this.pageType = ''; 437 GlobalContext.get().setObject('cameraNeedStatus', CameraNeedStatus.CAMERA_NO_NEED_TO_DO); 438 this.isForegroundInit = true; 439 this.calledByOther(); 440 this.mAction.initCamera(this.state.curCameraPosition, this.state.mode); 441 Log.info(`${this.TAG} onForegroundInit X`); 442 } 443 444 private calledByOther(): void { 445 Log.info(`${this.TAG} calledByOther invoke E`); 446 let from: string = ""; 447 let action: string = ""; 448 449 if (GlobalContext.get().getCameraAbilityWant()) { 450 Log.info(`${this.TAG} cameraAbilityWant: ${JSON.stringify(GlobalContext.get().getCameraAbilityWant())}`); 451 if (GlobalContext.get().getCameraAbilityWant()?.parameters?.from) { 452 from = GlobalContext.get().getCameraAbilityWant()?.parameters?.from as string; 453 } 454 const wantAction: string | undefined = GlobalContext.get().getCameraAbilityWant()?.action; 455 if (wantAction) { 456 action = wantAction; 457 } 458 } else { 459 this.mAction.thirdPartyCall(false, ""); 460 return; 461 } 462 Log.info(`${this.TAG} from: ${from} action: ${action}`); 463 464 if (from === "FA") { 465 Log.info(`from === "FA"`); 466 if (GlobalContext.get().getCameraAbilityWant()?.parameters?.action) { 467 action = GlobalContext.get().getCameraAbilityWant()?.parameters?.action as string; 468 } 469 this.mAction.faCall(true); 470 this.mAction.thirdPartyCall(false, ""); 471 this.initStateMode(action); 472 } else if (GlobalContext.get().getCameraAbilityWant()?.parameters?.supportMultiMode || action != "") { 473 this.mAction.faCall(false); 474 if (GlobalContext.get().getCameraAbilityWant()?.parameters?.supportMultiMode) { 475 action = 'ALL'; 476 this.mAction.thirdPartyCall(true, action); 477 this.initStateMode(action); 478 } else { 479 this.mAction.thirdPartyCall(true, action); 480 this.initStateMode(action); 481 } 482 } else { 483 this.mAction.faCall(false); 484 this.mAction.thirdPartyCall(false, ""); 485 } 486 Log.info(`${this.TAG} calledByOther invoke X: ${this.state.mode}`); 487 } 488 489 private initStateMode(action: string): void { 490 switch (action) { 491 case wantConstant.Action.ACTION_IMAGE_CAPTURE: 492 this.mAction.initMode('PHOTO'); 493 this.mAction.updateModeIndex(0); 494 break; 495 case wantConstant.Action.ACTION_VIDEO_CAPTURE: 496 this.mAction.initMode('VIDEO'); 497 this.mAction.updateModeIndex(1); 498 break; 499 case 'ALL': 500 this.mAction.initMode(this.state.mode); 501 this.mAction.updateModeIndex(this.state.modeIndex); 502 // private modeArray: Array<string> = ['PHOTO', 'VIDEO']; //, 'MORE'this.modeArray[modeIndex] 503 break; 504 default: 505 Log.info(`${this.TAG} FA default`); 506 break; 507 } 508 } 509 510 private updateCameraStatus(): void { 511 Log.info(`${this.TAG} updateCameraStatus cameraStatus: ${GlobalContext.get().getT<string>('cameraStatus')} 512 cameraNeedStatus: ${GlobalContext.get().getT<string>('cameraNeedStatus')}`); 513 514 if (this.canInit() && GlobalContext.get().getT<string>('cameraNeedStatus') == CameraNeedStatus.CAMERA_NEED_INIT) { 515 this.onForegroundInit(); 516 } 517 if (this.canRelease() && GlobalContext.get() 518 .getT<string>('cameraNeedStatus') == CameraNeedStatus.CAMERA_NEED_RELEASE) { 519 this.releaseCamera(); 520 } 521 Log.info(`${this.TAG} updateCameraStatus X`); 522 } 523 524 private canInit(): boolean { 525 //相机状态是首次加载或者session释放完成状态,才能进行初始化操作 526 return GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_BEFORE_VALUE || 527 GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_RELEASE_FINISHED; 528 } 529 530 private canRelease(): boolean { 531 //相机状态是预览完成状态或录像完成状态才能进行释放操作 532 return GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_PREVIEW_FINISHED || 533 GlobalContext.get().getT<string>('cameraStatus') == CameraStatus.CAMERA_TAKE_VIDEO_FINISHED; 534 } 535 536 onBackPress(): void { 537 Log.info(`${this.TAG} previewAreaLand onBackPress called`); 538 } 539 540 onPageHide(): void { 541 this.mAction.startVideoFlag(false); 542 } 543 544 private pinchGestureStart(event: GestureEvent): void { 545 Log.info(`${this.TAG} pinchGestureStart E`); 546 if (this.state.mode != 'MULTI' && this.state.curCameraPosition !== 'FRONT') { 547 clearTimeout(this.pinchGestureTimer); 548 this.mAction.updateIsShowZoomText(true); 549 this.mAction.updateShowPinch(true); 550 this.mAction.updateShowZoomLabelValue(false); 551 this.baseZoom = this.state.zoomRatio; 552 } 553 Log.info(`${this.TAG} pinchGestureStart X`); 554 } 555 556 private pinchGestureUpdate(event: GestureEvent): void { 557 Log.info(`${this.TAG} pinchGestureUpdate E`); 558 if (this.state.mode != 'MULTI' && this.state.curCameraPosition !== 'FRONT') { 559 let zoomRatio = event.scale + this.baseZoom - 1; 560 if (zoomRatio > 6) { 561 zoomRatio = 6; 562 } 563 if (zoomRatio < 1) { 564 zoomRatio = 1; 565 } 566 this.mAction.changeZoomRatio(zoomRatio); 567 } 568 Log.info(`${this.TAG} pinchGestureUpdate X`); 569 } 570 571 private pinchGestureEnd(event: GestureEvent): void { 572 Log.info(`${this.TAG} pinchGestureEnd E`); 573 if (this.state.mode != 'MULTI' && this.state.curCameraPosition !== 'FRONT') { 574 this.mAction.updateShowZoomLabelValue(true); 575 this.mAction.updateShowPinch(false); 576 this.pinchGestureTimer = setTimeout(() => { 577 this.mAction.updateIsShowZoomText(false); 578 }, 2000); 579 } 580 Log.info(`${this.TAG} pinchGestureEnd X`); 581 } 582 583 private onPreviewClicked(): void { 584 Log.info(`${this.TAG} click preview isShowtimeLapse= ${this.state.isShowtimeLapse} state.mode= ${this.state.mode}`); 585 if (this.state.mode === 'PHOTO' && this.state.isShowtimeLapse) { 586 this.mAction.changeTimeLapse(false); 587 this.mAction.capture(); 588 } else if (this.state.mode === 'VIDEO' && this.state.isShowtimeLapse) { 589 this.mAction.changeTimeLapse(false); 590 this.mAction.startRecording(); 591 } 592 } 593 594 private swipeChangeMode(swipe: number): void { 595 Log.info(`${this.TAG} swipeChangeMode E`); 596 if (!this.state.modeChangeDone && this.state.modeIndex + swipe >= 0 && this.state.modeIndex + swipe <= this.modeArray.length - 1 && !this.state.isShowtimeLapse) { 597 this.mAction.swipeChangeMode(this.state.modeIndex + swipe); 598 this.mAction.swipeModeChangeDone(true); 599 } 600 Log.info(`${this.TAG} swipeChangeMode X`); 601 } 602 603 private onKeepScreen(data: KeepScreenOnStruct): void { 604 Log.info(`${this.TAG} onKeepScreen E`); 605 if (data) { 606 GlobalContext.get() 607 .getCameraWinClass() 608 .setKeepScreenOn(data.isKeepScreenOn) 609 .then(() => { 610 Log.info('Succeeded in setting the screen to be always on'); 611 }) 612 .catch((err: BusinessError) => { 613 Log.error('Failed to set the screen to be always on. Cause: ' + JSON.stringify(err)); 614 }); 615 } 616 Log.info(`${this.TAG} onKeepScreen X`); 617 } 618 619 build() { 620 Column() { 621 if (this.state.isShowPreview) { 622 Stack() { 623 XComponent({ 624 id: '', 625 type: 'surface', 626 libraryname: '', 627 controller: GlobalContext.get().getXComponentController() 628 }) 629 .onLoad(() => { 630 Log.end(Log.X_COMPONENT_LIFE); 631 Log.info(`${this.TAG} XComponent_onLoad `); 632 let surfaceId: number = GlobalContext.get().getXComponentController().getXComponentSurfaceId(); 633 this.mAction.prepareSurface(surfaceId); 634 this.doCameraAction(); 635 }) 636 .width(this.state.xComponentWidth) 637 .height(this.state.xComponentHeight) 638 .animation({ 639 duration: 100, 640 curve: Curve.Sharp, 641 delay: 0, 642 iterations: 1, 643 playMode: PlayMode.Normal 644 }) 645 646 if (this.isSwitchBackground) { 647 Column() { 648 } 649 .width(this.state.xComponentWidth) 650 .height(this.state.xComponentHeight) 651 .backgroundColor('#000') 652 .opacity(this.state.switchBackgroundOpacity) 653 } 654 655 if (this.state.showBlur) { 656 Column() 657 .width(this.state.xComponentWidth) 658 .height(this.state.xComponentHeight) 659 .backgroundColor(Color.Black) 660 .border({ width: { top: 0.5, bottom: 0.5 }, color: Color.Black }) 661 } 662 663 if (this.btnSwitch) { 664 Image($r('app.media.whitePicture')) 665 .width(this.state.xComponentWidth) 666 .height(this.state.xComponentHeight) 667 .syncLoad(false) 668 .scale({ y: 1.0 }) 669 .rotate({ x: 0, y: 10, z: 0, angle: this.state.rotateAngle })// .opacity(this.state.btnOpacity_first) 670 .onComplete(() => { 671 }) 672 } 673 674 if (this.btnSwitchSec) { 675 Image($r('app.media.whitePicture')) 676 .width(this.state.xComponentWidth) 677 .height(this.state.xComponentHeight) 678 .syncLoad(false) 679 .scale({ y: 1.0 }) 680 .rotate({ x: 0, y: 10, z: 0, angle: this.state.rotateAngleSec })// .opacity(this.state.btnOpacity_sec) 681 .onComplete(() => { 682 }) 683 } 684 685 if (this.state.isShowFlashBlack) { 686 ShowFlashBlack(); 687 } 688 689 if (this.state.isShowZoomText && deviceInfo.deviceType !== "default" && !this.state.isShowtimeLapse) { 690 Stack({ alignContent: Alignment.Top }) { 691 ZoomText({ state: $state }) 692 } 693 .width('100%') 694 .height('96%') 695 } 696 697 if (this.state.isShowBigText) { 698 Stack({ alignContent: Alignment.BottomStart }) { 699 BigText() 700 } 701 .width('100%') 702 .height('100%') 703 .padding({ bottom: '40vp' }) 704 } 705 706 if (this.state.isAssGridViewShow === '1' && this.state.mode !== 'MORE') { 707 AssistiveGridView(); 708 } 709 710 if (this.state.isSmallVideoTimerVisible) { 711 SmallVideoTimer(); 712 } 713 714 if (this.state.isBigVideoTimerVisible) { 715 BigVideoTimer(); 716 } 717 718 if (this.state.isShowtimeLapse) { 719 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 720 Column() { 721 TimeLapseView(); 722 }.width('100%').height(150) 723 } 724 } 725 } 726 .width('100%') 727 .height('100%') 728 } 729 } 730 .height('100%') 731 .width(this.state.xComponentWidth) 732 .aspectRatio(this.mAspectRatio) 733 .margin({ top: 0 }) 734 .backgroundColor('#000') 735 .gesture( 736 GestureGroup( 737 GestureMode.Exclusive, 738 TapGesture({ fingers: 1, count: 1 }) 739 .onAction(() => this.onPreviewClicked()), 740 PinchGesture({ fingers: 2, distance: 1 }) 741 .onActionStart((event) => { 742 if (event === undefined) return; 743 this.pinchGestureStart(event) 744 }) 745 .onActionUpdate((event) => { 746 if (event === undefined) return; 747 this.pinchGestureUpdate(event) 748 }) 749 .onActionEnd((event) => { 750 if (event === undefined) return; 751 this.pinchGestureEnd(event) 752 }), 753 PanGesture({ fingers: 1, direction: PanDirection.Left, distance: 10 }) 754 .onActionEnd(() => { 755 if (!this.state.isThirdPartyCall && !GlobalContext.get().getCameraAbilityWant()?.parameters?.from) { 756 this.swipeChangeMode(1); 757 } 758 }), 759 PanGesture({ fingers: 1, direction: PanDirection.Right, distance: 10 }) 760 .onActionEnd(() => { 761 if (!this.state.isThirdPartyCall && !GlobalContext.get().getCameraAbilityWant()?.parameters?.from) { 762 this.swipeChangeMode(-1); 763 } 764 }) 765 ) 766 ) 767 } 768}