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