1# @ohos.multimedia.movingphotoview (MovingPhotoView) 2<!--Kit: Media Library Kit--> 3<!--Subsystem: FileManagement--> 4<!--Owner: @tangye123456--> 5<!--SE: @YanSanzo--> 6<!--TSE: @tinygreyy--> 7 8The **MovingPhotoView** component is used to play moving photos and control the playback status. 9 10> **NOTE** 11> 12> This component is supported since API version 12. Updates will be marked with a superscript to indicate their earliest API version. 13> 14> Currently, the **MovingPhotoView** component cannot be used in Previewer. 15 16## Modules to Import 17 18``` 19import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 20``` 21 22## MovingPhotoView 23 24> **NOTE** 25> 26> - Currently, live attributes cannot be set. 27> - Currently, **expandSafeArea** in the ArkUI common attribute **ComponentOptions** cannot be set. 28> - When this component is long pressed to trigger playback, the component area is zoomed in to 1.1 times. 29> - This component uses [AVPlayer](../apis-media-kit/arkts-apis-media-AVPlayer.md) to play moving photos. A maximum of three AVPlayers can be used at the same time. Otherwise, frame freezing may occur. 30 31MovingPhotoView(options: MovingPhotoViewOptions) 32 33**Parameters** 34 35 36| Name | Type | Mandatory| Description | 37| ------- | --------------------------------------------------------- | ---- | -------------- | 38| options | [MovingPhotoViewOptions](#movingphotoviewoptions) | Yes | Moving photo information.| 39 40## MovingPhotoViewOptions 41 42 43| Name | Type | Mandatory| Description | 44| ----------- | ------------------------------------------------------------------------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- | 45| movingPhoto | [MovingPhoto](arkts-apis-photoAccessHelper-MovingPhoto.md) | Yes | MovingPhoto instance. For details, see [MovingPhoto](arkts-apis-photoAccessHelper-MovingPhoto.md).<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 46| controller | [MovingPhotoViewController](#movingphotoviewcontroller) | No | Controller used to control the playback status of the moving photo.<br>**Atomic service API**: This API can be used in atomic services since API version 12. | 47| imageAIOptions<sup>18+</sup> | [ImageAIOptions](../apis-arkui/arkui-ts/ts-image-common.md#imageaioptions) | No | AI options. You can set the image analyzer type or bind an image analyzer controller.<br>**Atomic service API**: This API can be used in atomic services since API version 18.| 48 49## Properties 50 51In addition to the [universal properties](../apis-arkui/arkui-ts/ts-component-general-attributes.md), the following properties are supported. 52 53### muted 54 55muted(isMuted: boolean) 56 57Sets whether to mute the player. 58 59**Atomic service API**: This API can be used in atomic services since API version 12. 60 61**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 62 63**Parameters** 64 65 66| Name | Type | Mandatory| Description | 67| ------- | ------- | ---- | ---------------------------- | 68| isMuted | boolean | Yes | Whether to mute the player.<br>The default value is **false**.<br>**true** to mute, **false** otherwise.| 69 70### objectFit 71 72objectFit(value: ImageFit) 73 74Sets the display mode of the moving photo. 75 76**Atomic service API**: This API can be used in atomic services since API version 12. 77 78**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 79 80**Parameters** 81 82 83| Name| Type | Mandatory| Description | 84| ------ | ----------------------------------------------------------------------------- | ---- | -------------------------------- | 85| value | [ImageFit](../apis-arkui/arkui-ts/ts-appendix-enums.md#imagefit) | Yes | Image scale type.<br>The default value is **Cover**.| 86 87### autoPlayPeriod<sup>13+</sup> 88 89autoPlayPeriod(startTime: number, endTime: number) 90 91Sets the autoplay period, which is a configuration item of **autoPlay**. 92 93Before this API is called, [autoPlay](#autoplay13) must be set to **true**. Otherwise, the specified video play period (**startTime**, **endTime**) does not take effect. 94 95**Atomic service API**: This API can be used in atomic services since API version 13. 96 97**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 98 99**Parameters** 100 101 102| Name | Type | Mandatory| Description | 103| ------- | ------- | ---- | ---------------------------- | 104| startTime| number| Yes | Start playback time, in ms.<br>The value must be greater than or equal to 0.| 105| endTime| number| Yes | End playback time, in ms.<br>The value must be greater than **startTime**.| 106 107### autoPlay<sup>13+</sup> 108 109autoPlay(isAutoPlay: boolean) 110 111Sets whether to automatically play the video once. 112 113You can call this API when the moving photo is loaded and ready to play. After playback, a static image is displayed. 114 115**Atomic service API**: This API can be used in atomic services since API version 13. 116 117**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 118 119**Parameters** 120 121 122| Name | Type | Mandatory| Description | 123| ------- | ------- | ---- | ---------------------------- | 124| isAutoPlay| boolean| Yes | Whether to enable autoplay.<br>**true** to enable, **false** otherwise.<br>The default value is **false**.| 125 126### repeatPlay<sup>13+</sup> 127 128repeatPlay(isRepeatPlay: boolean) 129 130Sets repeat play. **repeatPlay** is mutually exclusive with **autoPlay** and **Long Press**, and takes precedence over them. 131 132**Atomic service API**: This API can be used in atomic services since API version 13. 133 134**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 135 136**Parameters** 137 138 139| Name | Type | Mandatory| Description | 140| ------- | ------- | ---- | ---------------------------- | 141| isRepeatPlay| boolean| Yes | Whether to enable repeat play.<br>**true** to enable, **false** otherwise.<br>The default value is **false**.| 142 143### enableAnalyzer<sup>18+</sup> 144 145enableAnalyzer(enabled: boolean) 146 147Sets the AI analyzer. Currently, the AI analyzer supports features, such as subject recognition, text recognition, and object search. 148 149**Atomic service API**: This API can be used in atomic services since API version 18. 150 151**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 152 153**Parameters** 154 155 156| Name | Type | Mandatory| Description | 157| ------- | ------- | ---- | ---------------------------- | 158| enabled| boolean| Yes | Whether to enable the AI analyzer.<br>**true** to enable, **false** otherwise.<br>The default value is **true**.| 159 160## Events 161 162In addition to [universal events](../apis-arkui/arkui-ts/ts-component-general-events.md), the following events are supported. 163 164### onComplete<sup>13+</sup> 165 166onComplete(callback: MovingPhotoViewEventCallback) 167 168Called when the image of a moving photo is loaded. 169 170**Atomic service API**: This API can be used in atomic services since API version 13. 171 172**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 173 174**Parameters** 175 176 177| Name | Type | Mandatory| Description | 178| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 179| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the image of a moving photo is loaded.| 180 181### onStart 182 183onStart(callback: MovingPhotoViewEventCallback) 184 185Called when a moving photo starts playing. 186 187**Atomic service API**: This API can be used in atomic services since API version 12. 188 189**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 190 191**Parameters** 192 193 194| Name | Type | Mandatory| Description | 195| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 196| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when a moving photo starts playing.| 197 198### onPause 199 200onPause(callback: MovingPhotoViewEventCallback) 201 202Called when the playback is paused. 203 204**Atomic service API**: This API can be used in atomic services since API version 12. 205 206**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 207 208**Parameters** 209 210 211| Name | Type | Mandatory| Description | 212| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 213| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo is paused.| 214 215### onFinish 216 217onFinish(callback: MovingPhotoViewEventCallback) 218 219Called when the playback is finished. 220 221**Atomic service API**: This API can be used in atomic services since API version 12. 222 223**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 224 225**Parameters** 226 227 228| Name | Type | Mandatory| Description | 229| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 230| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo ends.| 231 232### onError 233 234onError(callback: MovingPhotoViewEventCallback) 235 236Called when the playback fails. 237 238**Atomic service API**: This API can be used in atomic services since API version 12. 239 240**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 241 242**Parameters** 243 244 245| Name | Type | Mandatory| Description | 246| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 247| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo fails.| 248 249### onStop 250 251onStop(callback: MovingPhotoViewEventCallback) 252 253Called when the playback is stopped by **stop()**. 254 255**Atomic service API**: This API can be used in atomic services since API version 12. 256 257**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 258 259**Parameters** 260 261 262| Name | Type | Mandatory| Description | 263| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 264| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo is stopped.| 265 266### onPrepared<sup>20+</sup> 267 268onPrepared(callback: MovingPhotoViewEventCallback) 269 270Called when a moving photo is ready for playback. 271 272**Atomic service API**: This API can be used in atomic services since API version 20. 273 274**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 275 276**Parameters** 277 278 279| Name | Type | Mandatory| Description | 280| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 281| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the moving photo is ready for playback.| 282 283## MovingPhotoViewEventCallback 284 285declare type MovingPhotoViewEventCallback = () => void 286 287Defines a callback to be invoked when the playback status of a moving photo changes. 288 289**Atomic service API**: This API can be used in atomic services since API version 12. 290 291**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 292 293## MovingPhotoViewController 294 295A MovingPhotoViewController object can be used to control a **MovingPhotoView** component. For details, see [@ohos.multimedia.media](../apis-media-kit/arkts-apis-media.md). 296 297### constructor 298 299constructor(): void 300 301Constructs a MovingPhotoViewController object. 302 303**Atomic service API**: This API can be used in atomic services since API version 12. 304 305**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 306 307### startPlayback 308 309startPlayback(): void 310 311Starts playback. You can call this API when a moving photo is loaded and is ready to play, or when playback is paused or has finished. 312 313**Atomic service API**: This API can be used in atomic services since API version 12. 314 315**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 316 317### stopPlayback 318 319stopPlayback(): void 320 321Stops playback. Once started again, the playback starts from the beginning. 322 323**Atomic service API**: This API can be used in atomic services since API version 12. 324 325**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 326 327### refreshMovingPhoto<sup>18+</sup> 328 329refreshMovingPhoto(): void 330 331Forcibly refreshes the video and image resources loaded by the **MovingPhotoView** component. This API will interrupt the ongoing actions of the component. Exercise caution when using it. 332 333**Atomic service API**: This API can be used in atomic services since API version 18. 334 335**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 336 337## Example 1: Playing Moving Photos in Multiple Modes 338 339```ts 340// xxx.ets 341import { photoAccessHelper } from '@kit.MediaLibraryKit'; 342import { emitter } from '@kit.BasicServicesKit'; 343import { dataSharePredicates } from '@kit.ArkData'; 344import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 345 346const PHOTO_SELECT_EVENT_ID: number = 80001 347 348@Entry 349@Component 350struct MovingPhotoViewDemo { 351 @State src: photoAccessHelper.MovingPhoto | undefined = undefined 352 @State isMuted: boolean = false 353 controller: MovingPhotoViewController = new MovingPhotoViewController() 354 private uiContext: UIContext = this.getUIContext() 355 356 aboutToAppear(): void { 357 emitter.on({ 358 eventId: PHOTO_SELECT_EVENT_ID, 359 priority: emitter.EventPriority.IMMEDIATE, 360 }, (eventData: emitter.EventData) => { 361 this.src = AppStorage.get<photoAccessHelper.MovingPhoto>('mv_data') as photoAccessHelper.MovingPhoto 362 }) 363 } 364 365 aboutToDisappear(): void { 366 emitter.off(PHOTO_SELECT_EVENT_ID) 367 } 368 369 build() { 370 Column() { 371 Row() { 372 Button('PICK') 373 .margin(5) 374 .onClick(async () => { 375 try { 376 let uris: Array<string> = [] 377 const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions() 378 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE 379 photoSelectOptions.maxSelectNumber = 2 380 const photoViewPicker = new photoAccessHelper.PhotoViewPicker() 381 let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions) 382 uris = photoSelectResult.photoUris 383 if (uris[0]) { 384 this.handlePickerResult(this.uiContext.getHostContext()!, uris[0], new MediaDataHandlerMovingPhoto()) 385 } 386 } catch (e) { 387 console.error(`pick file failed`) 388 } 389 }) 390 } 391 .alignItems(VerticalAlign.Center) 392 .justifyContent(FlexAlign.Center) 393 .height('15%') 394 395 Row() { 396 Column() { 397 MovingPhotoView({ 398 movingPhoto: this.src, 399 controller: this.controller 400 }) 401 .width('100%') 402 .height('100%') 403 .muted(this.isMuted) 404 .autoPlay(true) 405 .repeatPlay(false) 406 .autoPlayPeriod(0, 600) 407 .objectFit(ImageFit.Cover) 408 .onComplete(() => { 409 console.log('Completed'); 410 }) 411 .onStart(() => { 412 console.log('onStart') 413 }) 414 .onFinish(() => { 415 console.log('onFinish') 416 }) 417 .onStop(() => { 418 console.log('onStop') 419 }) 420 .onError(() => { 421 console.log('onError') 422 }) 423 } 424 } 425 .height('70%') 426 427 Row() { 428 Button('start') 429 .onClick(() => { 430 this.controller.startPlayback() 431 }) 432 .margin(5) 433 Button('stop') 434 .onClick(() => { 435 this.controller.stopPlayback() 436 }) 437 .margin(5) 438 Button('mute') 439 .onClick(() => { 440 this.isMuted = !this.isMuted 441 }) 442 .margin(5) 443 } 444 .alignItems(VerticalAlign.Center) 445 .justifyContent(FlexAlign.Center) 446 .height('15%') 447 } 448 } 449 450 async handlePickerResult(context: Context, uri: string, handler: photoAccessHelper.MediaAssetDataHandler<photoAccessHelper.MovingPhoto>): Promise<void> { 451 let uriPredicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates(); 452 uriPredicates.equalTo('uri', uri) 453 let fetchOptions: photoAccessHelper.FetchOptions = { 454 fetchColumns: [], 455 predicates: uriPredicates 456 }; 457 let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context) 458 let assetResult = await phAccessHelper.getAssets(fetchOptions) 459 let asset = await assetResult.getFirstObject() 460 let requestOptions: photoAccessHelper.RequestOptions = { 461 deliveryMode: photoAccessHelper.DeliveryMode.FAST_MODE, 462 } 463 try { 464 photoAccessHelper.MediaAssetManager.requestMovingPhoto(context, asset, requestOptions, handler) 465 } catch (err) { 466 console.error("request error: ", err) 467 } 468 } 469} 470 471class MediaDataHandlerMovingPhoto implements photoAccessHelper.MediaAssetDataHandler<photoAccessHelper.MovingPhoto> { 472 async onDataPrepared(movingPhoto: photoAccessHelper.MovingPhoto) { 473 AppStorage.setOrCreate('mv_data', movingPhoto) 474 emitter.emit({ 475 eventId: PHOTO_SELECT_EVENT_ID, 476 priority: emitter.EventPriority.IMMEDIATE, 477 }, { 478 }) 479 } 480} 481``` 482 483## Example 2: Using Moving Photos in Atomic Services 484 485```ts 486// xxx.ets 487import { photoAccessHelper, MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 488 489let data: photoAccessHelper.MovingPhoto 490async function loading(context: Context) { 491 try { 492 // Ensure that the media assets corresponding to imageFileUri and videoFileUri exist in the application sandbox directory. 493 let imageFileUri = 'file://{bundleName}/data/storage/el2/base/haps/entry/files/xxx.jpg'; 494 let videoFileUri = 'file://{bundleName}/data/storage/el2/base/haps/entry/files/xxx.mp4'; 495 data = await photoAccessHelper.MediaAssetManager.loadMovingPhoto(context, imageFileUri, videoFileUri); 496 console.info('load moving photo successfully'); 497 } catch (err) { 498 console.error(`load moving photo failed with error: ${err.code}, ${err.message}`); 499 } 500} 501@Entry 502@Component 503struct Index { 504 controller: MovingPhotoViewController = new MovingPhotoViewController() 505 private uiContext: UIContext = this.getUIContext() 506 @State ImageFit: ImageFit | undefined | null = ImageFit.Contain; 507 @State flag: boolean = true; 508 @State autoPlayFlag: boolean = true; 509 @State repeatPlayFlag: boolean = false; 510 @State autoPlayPeriodStart: number = 0; 511 @State autoPlayPeriodEnd: number = 500; 512 aboutToAppear(): void { 513 loading(this.uiContext.getHostContext()!) 514 } 515 516 build() { 517 NavDestination() { 518 Column() { 519 Stack({ alignContent: Alignment.BottomStart }) { 520 MovingPhotoView({ 521 movingPhoto: data, 522 controller: this.controller 523 }) 524 .width(300) 525 .height(400) 526 .muted(this.flag) 527 .objectFit(this.ImageFit) 528 .autoPlay(this.autoPlayFlag) 529 .autoPlayPeriod(this.autoPlayPeriodStart, this.autoPlayPeriodEnd) 530 .repeatPlay(this.repeatPlayFlag) 531 .onComplete(() => { 532 console.info('onComplete') 533 }) 534 .onStart(() => { 535 console.info('onStart') 536 }) 537 .onStop(() => { 538 console.info('onStop') 539 }) 540 .onPause(() => { 541 console.info('onPause') 542 }) 543 .onFinish(() => { 544 console.info('onFinish') 545 }) 546 .onError(() => { 547 console.info('onError') 548 }) 549 } 550 551 Row() { 552 Button('Play') 553 .onClick(() => { 554 this.controller.startPlayback() 555 }) 556 Button('StopPlay') 557 .onClick(() => { 558 this.controller.stopPlayback() 559 }) 560 Button('refreshMovingPhoto') 561 .onClick(() => { 562 this.controller.refreshMovingPhoto() 563 }) 564 Button('mute').id('MovingPhotoView_true') 565 .onClick(() => { 566 this.flag = false 567 }) 568 } 569 } 570 } 571 } 572} 573``` 574 575<!--RPl--><!--RPlEnd--> 576