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