1# @ohos.multimedia.movingphotoview (动态照片) 2<!--Kit: Media Library Kit--> 3<!--Subsystem: FileManagement--> 4<!--Owner: @tangye123456--> 5<!--Designer: @YanSanzo--> 6<!--Tester: @tinygreyy--> 7<!--Adviser: @zengyawen--> 8 9用于播放动态照片文件并控制其播放状态的组件。 10 11> **说明:** 12> 13> 该组件从API Version 12开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 14> 当前不支持在预览器中使用MovingPhotoView组件。 15 16## 导入模块 17 18``` 19import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 20``` 21 22## MovingPhotoView 23 24> **说明:** 25> 26> - 当前不支持动态属性设置。 27> - 当前不支持ArkUI通用属性ComponentOptions中expandSafeArea属性设置。 28> - 该组件长按触发播放时组件区域放大为1.1倍。 29> - 该组件使用[AVPlayer](../apis-media-kit/arkts-apis-media-AVPlayer.md)进行播放,同时开启的AVPlayer个数不建议超过3个,超过3个可能会出现视频播放卡顿现象。 30 31MovingPhotoView(options: MovingPhotoViewOptions) 32 33**参数:** 34 35 36| 参数名 | 参数类型 | 必填 | 参数描述 | 37| ------- | --------------------------------------------------------- | ---- | -------------- | 38| options | [MovingPhotoViewOptions](#movingphotoviewoptions) | 是 | 动态照片信息。 | 39 40## MovingPhotoViewOptions 41 42 43| 参数名 | 参数类型 | 必填 | 参数描述 | 44| ----------- | ------------------------------------------------------------------------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- | 45| movingPhoto | [MovingPhoto](arkts-apis-photoAccessHelper-MovingPhoto.md) | 是 | 支持媒体库MovingPhoto数据源,具体信息详见[MovingPhoto说明](arkts-apis-photoAccessHelper-MovingPhoto.md)。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 46| controller | [MovingPhotoViewController](#movingphotoviewcontroller) | 否 | 设置动态照片控制器,可以控制动态照片的播放状态。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 47| imageAIOptions<sup>18+</sup> | [ImageAIOptions](../apis-arkui/arkui-ts/ts-image-common.md#imageaioptions12) | 否 | 设置动态照片AI分析选项,可配置分析类型或绑定一个分析控制器。<br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 | 48 49## 属性 50 51除支持[通用属性](../apis-arkui/arkui-ts/ts-component-general-attributes.md)外,还支持以下属性: 52 53### muted 54 55muted(isMuted: boolean) 56 57设置是否静音。 58 59**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 60 61**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 62 63**参数:** 64 65 66| 参数名 | 类型 | 必填 | 说明 | 67| ------- | ------- | ---- | ---------------------------- | 68| isMuted | boolean | 是 | 是否静音。<br/>默认值:false。<br/>false:非静音。<br/>true:静音。| 69 70### objectFit 71 72objectFit(value: ImageFit) 73 74设置动态照片显示模式。 75 76**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 77 78**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 79 80**参数:** 81 82 83| 参数名 | 类型 | 必填 | 说明 | 84| ------ | ----------------------------------------------------------------------------- | ---- | -------------------------------- | 85| value | [ImageFit](../apis-arkui/arkui-ts/ts-appendix-enums.md#imagefit) | 是 | 视频显示模式。<br/>默认值:Cover。 | 86 87### autoPlayPeriod<sup>13+</sup> 88 89autoPlayPeriod(startTime: number, endTime: number) 90 91设置自动播放区间,附属于autoPlay的子配置项。 92 93在调用此方法前,需将[autoPlay](#autoplay13)设置为true,设置自动播放,否则指定的视频区间(startTime, endTime)无法生效。 94 95**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 96 97**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 98 99**参数:** 100 101 102| 参数名 | 类型 | 必填 | 说明 | 103| ------- | ------- | ---- | ---------------------------- | 104| startTime| number| 是 | 区间播放开始时间,单位:ms。<br/>取值范围:大于等于0。| 105| endTime| number| 是 | 区间播放结束时间,单位:ms。<br/>取值范围:大于startTime。 | 106 107### autoPlay<sup>13+</sup> 108 109autoPlay(isAutoPlay: boolean) 110 111设置自动播放,自动播放一遍视频。 112 113动态照片加载完成后,准备播放时可以调用,播放完成后显示静态图。 114 115**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 116 117**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 118 119**参数:** 120 121 122| 参数名 | 类型 | 必填 | 说明 | 123| ------- | ------- | ---- | ---------------------------- | 124| isAutoPlay| boolean| 是 | 是否自动播放。<br/>false:不自动播放。<br/>true:自动播放。<br/>默认值:false。| 125 126### repeatPlay<sup>13+</sup> 127 128repeatPlay(isRepeatPlay: boolean) 129 130设置循环播放,重复播放视频。 repeatPlay与autoPlay及长按播放互斥,repeatPlay设置时,autoPlay和长按播放均不生效。 131 132**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 133 134**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 135 136**参数:** 137 138 139| 参数名 | 类型 | 必填 | 说明 | 140| ------- | ------- | ---- | ---------------------------- | 141| isRepeatPlay| boolean| 是 | 是否循环播放。<br/>false:不循环播放。<br/>true:循环播放。<br/>默认值:false。| 142 143### enableAnalyzer<sup>18+</sup> 144 145enableAnalyzer(enabled: boolean) 146 147设置该图片是否支持AI分析,当前支持主体识别、文字识别和对象查找等功能。 148 149**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 150 151**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 152 153**参数:** 154 155 156| 参数名 | 类型 | 必填 | 说明 | 157| ------- | ------- | ---- | ---------------------------- | 158| enabled| boolean| 是 | 是否开启AI分析。<br/>false:不开启AI分析。<br/>true:开启AI分析。<br/>默认值:true。| 159 160## 事件 161 162除支持[通用事件](../apis-arkui/arkui-ts/ts-component-general-events.md)外,还支持以下事件: 163 164### onComplete<sup>13+</sup> 165 166onComplete(callback: MovingPhotoViewEventCallback) 167 168动态照片加载完成图片时触发该事件。 169 170**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 171 172**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 173 174**参数:** 175 176 177| 参数名 | 类型 | 必填 | 说明 | 178| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 179| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片加载完成图片的回调。 | 180 181### onStart 182 183onStart(callback: MovingPhotoViewEventCallback) 184 185播放时触发该事件。 186 187**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 188 189**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 190 191**参数:** 192 193 194| 参数名 | 类型 | 必填 | 说明 | 195| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 196| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片开始播放时触发的回调。 | 197 198### onPause 199 200onPause(callback: MovingPhotoViewEventCallback) 201 202播放暂停时触发该事件。 203 204**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 205 206**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 207 208**参数:** 209 210 211| 参数名 | 类型 | 必填 | 说明 | 212| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 213| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片播放暂停时触发的回调。 | 214 215### onFinish 216 217onFinish(callback: MovingPhotoViewEventCallback) 218 219播放结束时触发该事件。 220 221**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 222 223**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 224 225**参数:** 226 227 228| 参数名 | 类型 | 必填 | 说明 | 229| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 230| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片播放结束时触发的回调。 | 231 232### onError 233 234onError(callback: MovingPhotoViewEventCallback) 235 236播放失败时触发该事件。 237 238**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 239 240**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 241 242**参数:** 243 244 245| 参数名 | 类型 | 必填 | 说明 | 246| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 247| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片播放失败时触发的回调。 | 248 249### onStop 250 251onStop(callback: MovingPhotoViewEventCallback) 252 253播放停止时触发该事件(当stop()方法被调用后触发)。 254 255**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 256 257**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 258 259**参数:** 260 261 262| 参数名 | 类型 | 必填 | 说明 | 263| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 264| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片停止播放时触发的回调。 | 265 266### onPrepared<sup>20+</sup> 267 268onPrepared(callback: MovingPhotoViewEventCallback) 269 270动态照片准备播放时触发该事件。 271 272**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 273 274**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 275 276**参数:** 277 278 279| 参数名 | 类型 | 必填 | 说明 | 280| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 281| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | 是 | 动态照片准备播放时的回调。 | 282 283## MovingPhotoViewEventCallback 284 285declare type MovingPhotoViewEventCallback = () => void 286 287动态照片播放状态发生变化时触发的回调。 288 289**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 290 291**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 292 293## MovingPhotoViewController 294 295一个MovingPhotoViewController对象可以控制一个MovingPhotoView,可用视频播放实例请参考[@ohos.multimedia.media](../apis-media-kit/arkts-apis-media.md)。 296 297### constructor 298 299constructor() 300 301MovingPhotoViewController的构造函数。 302 303**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 304 305**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 306 307### startPlayback 308 309startPlayback() 310 311开始播放,动态照片加载完成后,在播放准备,暂停,完成时调用。 312 313**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 314 315**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 316 317### stopPlayback 318 319stopPlayback() 320 321停止播放,再次播放时从头开始播放。 322 323**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 324 325**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 326 327### refreshMovingPhoto<sup>18+</sup> 328 329refreshMovingPhoto() 330 331强制刷新动态照片组件加载的视频和图片资源,会打断组件当前的行为,使用时要谨慎。 332 333**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 334 335**系统能力:** SystemCapability.FileManagement.PhotoAccessHelper.Core 336 337## 示例1:多种形式播放动态照片 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## 示例2:在原子化服务中使用动态照片 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 // 需要确保imageFileUri和videoFileUri对应的资源在应用沙箱存在。 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 576<!--RP1--><!--RP1End-->