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