• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ImageAnimator
2
3提供帧动画组件来实现逐帧播放图片的能力,可以配置需要播放的图片列表,每张图片可以配置时长。
4
5>  **说明:**
6>
7> 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8
9
10
11## 子组件
12
1314
15
16## 接口
17
18ImageAnimator()
19
20**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
21
22**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
23
24**系统能力:** SystemCapability.ArkUI.ArkUI.Full
25
26## 属性
27
28除支持[通用属性](ts-component-general-attributes.md)外,还支持以下属性:
29
30### images
31
32images(value: Array<ImageFrameInfo>)
33
34设置图片帧信息集合。不支持动态更新。
35
36**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
37
38**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
39
40**系统能力:** SystemCapability.ArkUI.ArkUI.Full
41
42**参数:**
43
44| 参数名 | 类型                                                   | 必填 | 说明                                                         |
45| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
46| value  | Array&lt;[ImageFrameInfo](#imageframeinfo对象说明)&gt; | 是   | 设置图片帧信息集合。每一帧的帧信息(ImageFrameInfo)包含图片路径、图片大小、图片位置和图片播放时长信息,详见ImageFrameInfo属性说明。<br/>默认值:[] <br/> **说明:** 传入数组的内容过大时,内存占用会随之升高。此内存由开发者自行控制。因此,开发者在传入数据前,请充分评估内存消耗情况,以避免内存不足等问题。 |
47
48### state
49
50state(value: AnimationStatus)
51
52控制播放状态。
53
54**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
55
56**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
57
58**系统能力:** SystemCapability.ArkUI.ArkUI.Full
59
60**参数:**
61
62| 参数名 | 类型                                                    | 必填 | 说明                                                         |
63| ------ | ------------------------------------------------------- | ---- | ------------------------------------------------------------ |
64| value  | [AnimationStatus](ts-appendix-enums.md#animationstatus) | 是   | 默认为初始状态,用于控制播放状态。<br/>默认值:AnimationStatus.Initial |
65
66### duration
67
68duration(value: number)
69
70设置播放时长。当Images中任意一帧图片设置了单独的duration后,该属性设置无效。
71
72**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
73
74**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
75
76**系统能力:** SystemCapability.ArkUI.ArkUI.Full
77
78**参数:**
79
80| 参数名 | 类型   | 必填 | 说明                                                         |
81| ------ | ------ | ---- | ------------------------------------------------------------ |
82| value  | number | 是   | 播放时长。<br/>value为0时,不播放图片。<br/>value的改变只会在下一次循环开始时生效。<br/>单位:毫秒<br/>默认值:1000ms |
83
84### reverse
85
86reverse(value: boolean)
87
88设置播放方向。
89
90**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
91
92**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
93
94**系统能力:** SystemCapability.ArkUI.ArkUI.Full
95
96**参数:**
97
98| 参数名 | 类型    | 必填 | 说明                                                         |
99| ------ | ------- | ---- | ------------------------------------------------------------ |
100| value  | boolean | 是   | 播放方向。<br/>false表示从第1张图片播放到最后1张图片,true表示从最后1张图片播放到第1张图片。<br/>默认值:false |
101
102### fixedSize
103
104fixedSize(value: boolean)
105
106设置图片大小是否固定为组件大小。
107
108**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
109
110**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
111
112**系统能力:** SystemCapability.ArkUI.ArkUI.Full
113
114**参数:**
115
116| 参数名 | 类型    | 必填 | 说明                                                         |
117| ------ | ------- | ---- | ------------------------------------------------------------ |
118| value  | boolean | 是   | 设置图片大小是否固定为组件大小。&nbsp;true表示图片大小与组件大小一致,此时设置图片的width&nbsp;、height&nbsp;、top&nbsp;和left属性是无效的。false表示每一张图片的width&nbsp;、height&nbsp;、top和left属性都要单独设置。<br/>默认值:true |
119
120### preDecode<sup>(deprecated)</sup>
121
122preDecode(value: number)
123
124设置预解码的图片数量。
125
126从API version 9开始废弃。
127
128**系统能力:** SystemCapability.ArkUI.ArkUI.Full
129
130**参数:**
131
132| 参数名 | 类型   | 必填 | 说明                                                         |
133| ------ | ------ | ---- | ------------------------------------------------------------ |
134| value  | number | 是   | 预解码的图片数量。例如该值设为2,则播放当前页时会提前加载后面两张图片至缓存以提升性能。<br/>默认值:0 |
135
136### fillMode
137
138fillMode(value: FillMode)
139
140设置当前播放方向下,动画开始前和结束后的状态。动画结束后的状态由fillMode和reverse属性共同决定。例如,fillMode为Forwards表示停止时维持动画最后一个关键帧的状态,若reverse为false则维持正播的最后一帧,即最后一张图,若reverse为true则维持逆播的最后一帧,即第一张图。
141
142**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
143
144**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
145
146**系统能力:** SystemCapability.ArkUI.ArkUI.Full
147
148**参数:**
149
150| 参数名 | 类型                                      | 必填 | 说明                                                         |
151| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
152| value  | [FillMode](ts-appendix-enums.md#fillmode) | 是   | 当前播放方向下,动画开始前和结束后的状态。<br/>默认值:FillMode.Forwards |
153
154### iterations
155
156iterations(value: number)
157
158设置播放次数。
159
160**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
161
162**系统能力:** SystemCapability.ArkUI.ArkUI.Full
163
164**参数:**
165
166| 参数名 | 类型   | 必填 | 说明                                                   |
167| ------ | ------ | ---- | ------------------------------------------------------ |
168| value  | number | 是   | 默认播放一次,设置为-1时表示无限次播放。<br/>默认值:1 |
169
170### monitorInvisibleArea<sup>17+</sup>
171
172monitorInvisibleArea(monitorInvisibleArea: boolean)
173
174设置组件是否通过系统[onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange)的可见性判定,控制组件的暂停和播放。
175
176**原子化服务API:** 从API version 17开始,该接口支持在原子化服务中使用。
177
178**系统能力:** SystemCapability.ArkUI.ArkUI.Full
179
180**参数:**
181
182| 参数名 | 类型   | 必填 | 说明                                                   |
183| ------ | ------ | ---- | ------------------------------------------------------ |
184| monitorInvisibleArea  | boolean | 是 | 当设置为true时,组件将基于系统的[onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange)可见性判定,控制组件的暂停与播放。<br/> 当组件的运行状态为[AnimationStatus](ts-appendix-enums.md#animationstatus)的Running时,若判定组件不可见,则自动执行暂停操作;若判定为可见,则自动恢复播放。<br/>默认值:false <br/> **说明:** <br/>当该属性由true动态修改为false时,组件将依据当前的[AnimationStatus](ts-appendix-enums.md#animationstatus)状态进行处理。<br/> 例如,若当前状态为Running且因[onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange)的不可见回调暂停,则在属性由true改为false后,组件会从上次暂停的位置重新开始播放。<br/>由该属性导致的不可见暂停和可见暂停操作不会改变用户设置的[state](./ts-basic-components-imageanimator.md#state)值。|
185
186## ImageFrameInfo对象说明
187
188**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
189
190**系统能力:** SystemCapability.ArkUI.ArkUI.Full
191
192| 名称   | 类型   | 必填 | 说明 |
193| -------- | -------------- | -------- | -------- |
194| src      | string \| [Resource](ts-types.md#resource)<sup>9+</sup> \| [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)<sup>12+</sup> | 是    | 图片路径,图片格式为jpg、jpeg、svg、png、bmp、webp、ico和heif,从API Version9开始支持[Resource](ts-types.md#resource)类型的路径,从API version 12开始支持[PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)类型。 <br/>**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。|
195| width    | number&nbsp;\|&nbsp;string | 否  | 图片宽度。string类型支持number类型取值的字符串形式,可以附带单位,例如"2"、"2px"。<br/>默认值:0<br/>单位:vp   <br/>**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用       |
196| height   | number&nbsp;\|&nbsp;string | 否  | 图片高度。string类型支持number类型取值的字符串形式,可以附带单位,例如"2"、"2px"。<br/>默认值:0<br/>单位:vp     <br/>**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用        |
197| top      | number&nbsp;\|&nbsp;string | 否  | 图片相对于组件左上角的纵向坐标。string类型支持number类型取值的字符串形式,可以附带单位,例如"2"、"2px"。<br/>默认值:0<br/>单位:vp  <br/>**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用  |
198| left     | number&nbsp;\|&nbsp;string | 否  | 图片相对于组件左上角的横向坐标。string类型支持number类型取值的字符串形式,可以附带单位,例如"2"、"2px"。<br/>默认值:0<br/>单位:vp <br/>**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用   |
199| duration | number          | 否     | 每一帧图片的播放时长,单位毫秒。<br/>默认值:0         |
200
201## 事件
202
203除支持[通用事件](ts-component-general-events.md)外,还支持以下事件:
204
205### onStart
206
207onStart(event:&nbsp;()&nbsp;=&gt;&nbsp;void)
208
209状态回调,动画开始播放时触发。
210
211**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
212
213**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
214
215**系统能力:** SystemCapability.ArkUI.ArkUI.Full
216
217### onPause
218
219onPause(event:&nbsp;()&nbsp;=&gt;&nbsp;void)
220
221状态回调,动画暂停播放时触发。
222
223**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
224
225**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
226
227**系统能力:** SystemCapability.ArkUI.ArkUI.Full
228
229### onRepeat
230
231onRepeat(event:&nbsp;()&nbsp;=&gt;&nbsp;void)
232
233状态回调,动画重复播放时触发。
234
235**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
236
237**系统能力:** SystemCapability.ArkUI.ArkUI.Full
238
239### onCancel
240
241onCancel(event:&nbsp;()&nbsp;=&gt;&nbsp;void)
242
243状态回调,动画返回最初状态时触发。
244
245**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
246
247**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
248
249**系统能力:** SystemCapability.ArkUI.ArkUI.Full
250
251### onFinish
252
253onFinish(event:&nbsp;()&nbsp;=&gt;&nbsp;void)
254
255状态回调,动画播放完成时或者停止播放时触发。
256
257**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。
258
259**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
260
261**系统能力:** SystemCapability.ArkUI.ArkUI.Full
262
263
264## 示例
265
266### 示例1(播放Resource动画)
267
268通过ImageAnimator组件播放Resource动画。
269
270```ts
271// xxx.ets
272@Entry
273@Component
274struct ImageAnimatorExample {
275  @State state: AnimationStatus = AnimationStatus.Initial
276  @State reverse: boolean = false
277  @State iterations: number = 1
278
279  build() {
280    Column({ space: 10 }) {
281      ImageAnimator()
282        .images([
283          {
284            src: $r('app.media.img1')
285          },
286          {
287            src: $r('app.media.img2')
288          },
289          {
290            src: $r('app.media.img3')
291          },
292          {
293            src: $r('app.media.img4')
294          }
295        ])
296        .duration(2000)
297        .state(this.state).reverse(this.reverse)
298        .fillMode(FillMode.None).iterations(this.iterations).width(340).height(240)
299        .margin({ top: 100 })
300        .onStart(() => {
301          console.info('Start')
302        })
303        .onPause(() => {
304          console.info('Pause')
305        })
306        .onRepeat(() => {
307          console.info('Repeat')
308        })
309        .onCancel(() => {
310          console.info('Cancel')
311        })
312        .onFinish(() => {
313          console.info('Finish')
314          this.state = AnimationStatus.Stopped
315        })
316      Row() {
317        Button('start').width(100).padding(5).onClick(() => {
318          this.state = AnimationStatus.Running
319        }).margin(5)
320        Button('pause').width(100).padding(5).onClick(() => {
321          this.state = AnimationStatus.Paused     // 显示当前帧图片
322        }).margin(5)
323        Button('stop').width(100).padding(5).onClick(() => {
324          this.state = AnimationStatus.Stopped    // 显示动画的起始帧图片
325        }).margin(5)
326      }
327
328      Row() {
329        Button('reverse').width(100).padding(5).onClick(() => {
330          this.reverse = !this.reverse
331        }).margin(5)
332        Button('once').width(100).padding(5).onClick(() => {
333          this.iterations = 1
334        }).margin(5)
335        Button('infinite').width(100).padding(5).onClick(() => {
336          this.iterations = -1 // 无限循环播放
337        }).margin(5)
338      }
339    }.width('100%').height('100%')
340  }
341}
342```
343
344### 示例2(播放PixelMap动画)
345
346通过ImageAnimator组件播放PixelMap动画。
347
348```ts
349// xxx.ets
350import { image } from '@kit.ImageKit'
351
352@Entry
353@Component
354struct ImageAnimatorExample {
355  imagePixelMap: Array<PixelMap> = []
356  @State state: AnimationStatus = AnimationStatus.Initial
357  @State reverse: boolean = false
358  @State iterations: number = 1
359  @State images:Array<ImageFrameInfo> = []
360  async aboutToAppear() {
361    this.imagePixelMap.push(await this.getPixmapFromMedia($r('app.media.icon')))
362    this.images.push({src:this.imagePixelMap[0]})
363  }
364  build() {
365    Column({ space: 10 }) {
366      ImageAnimator()
367        .images(this.images)
368        .duration(2000)
369        .state(this.state).reverse(this.reverse)
370        .fillMode(FillMode.None).iterations(this.iterations).width(340).height(240)
371        .margin({ top: 100 })
372        .onStart(() => {
373          console.info('Start')
374        })
375        .onPause(() => {
376          console.info('Pause')
377        })
378        .onRepeat(() => {
379          console.info('Repeat')
380        })
381        .onCancel(() => {
382          console.info('Cancel')
383        })
384        .onFinish(() => {
385          console.info('Finish')
386          this.state = AnimationStatus.Stopped
387        })
388      Row() {
389        Button('start').width(100).padding(5).onClick(() => {
390          this.state = AnimationStatus.Running
391        }).margin(5)
392        Button('pause').width(100).padding(5).onClick(() => {
393          this.state = AnimationStatus.Paused     // 显示当前帧图片
394        }).margin(5)
395        Button('stop').width(100).padding(5).onClick(() => {
396          this.state = AnimationStatus.Stopped    // 显示动画的起始帧图片
397        }).margin(5)
398      }
399      Row() {
400        Button('reverse').width(100).padding(5).onClick(() => {
401          this.reverse = !this.reverse
402        }).margin(5)
403        Button('once').width(100).padding(5).onClick(() => {
404          this.iterations = 1
405        }).margin(5)
406        Button('infinite').width(100).padding(5).onClick(() => {
407          this.iterations = -1 // 无限循环播放
408        }).margin(5)
409      }
410    }.width('100%').height('100%')
411  }
412
413  private async getPixmapFromMedia(resource: Resource) {
414    let unit8Array = await this.getUIContext().getHostContext()?.resourceManager?.getMediaContent({
415      bundleName: resource.bundleName,
416      moduleName: resource.moduleName,
417      id: resource.id
418    })
419    let imageSource = image.createImageSource(unit8Array?.buffer.slice(0, unit8Array.buffer.byteLength))
420    let createPixelMap: image.PixelMap = await imageSource.createPixelMap({
421      desiredPixelFormat: image.PixelMapFormat.RGBA_8888
422    })
423    await imageSource.release()
424    return createPixelMap
425  }
426}
427```
428
429![imageAnimator](figures/imageAnimator.gif)
430
431### 示例3(设置不可见自动停播)
432
433通过[monitorInvisibleArea](#monitorinvisiblearea17)实现了当ImageAnimator的[state](#state)为AnimationStatus.Running时,控制组件在不可见时停止播放,在可见时恢复播放。
434
435```ts
436@Entry
437@Component
438struct ImageAnimatorAutoPauseTest {
439  scroller: Scroller = new Scroller()
440  @State state: AnimationStatus = AnimationStatus.Running
441  @State reverse: boolean = false
442  @State iterations: number = 100
443  @State preCallBack: string = "Null"
444  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
445
446  build() {
447    Stack({ alignContent: Alignment.TopStart }) {
448      Scroll(this.scroller) {
449        Column() {
450          ImageAnimator()
451            .images([
452              {
453                src: $r('app.media.Clouds')
454              },
455              {
456                src: $r('app.media.landscape')
457              },
458              {
459                src: $r('app.media.sky')
460              },
461              {
462                src: $r('app.media.mountain')
463              }
464            ])
465            .borderRadius(10)
466            .monitorInvisibleArea(true)
467            .clip(true).duration(4000).state(this.state).reverse(this.reverse)
468            .fillMode(FillMode.Forwards).iterations(this.iterations).width(340).height(240)
469            .margin({ top: 100 })
470            .onStart(() => {
471              this.preCallBack = "Start"
472              console.info('ImageAnimator Start')
473            })
474            .onPause(() => {
475              this.preCallBack = "Pause"
476              console.info('ImageAnimator Pause')
477            })
478            .onRepeat(() => {
479              console.info('ImageAnimator Repeat')
480            })
481            .onCancel(() => {
482              console.info('ImageAnimator Cancel')
483            })
484            .onFinish(() => {
485              console.info('ImageAnimator Finish')
486            })
487          ForEach(this.arr, (item: number) => {
488            Text(item.toString())
489              .width('90%')
490              .height(150)
491              .backgroundColor(0xFFFFFF)
492              .borderRadius(15)
493              .fontSize(16)
494              .textAlign(TextAlign.Center)
495              .margin({ top: 10 })
496          }, (item: string) => item)
497        }.width('100%')
498      }
499      .scrollable(ScrollDirection.Vertical) // 滚动方向纵向
500      .scrollBar(BarState.On) // 滚动条常驻显示
501      .scrollBarColor(Color.Gray) // 滚动条颜色
502      .scrollBarWidth(10) // 滚动条宽度
503      .friction(0.6)
504      .edgeEffect(EdgeEffect.None)
505      .onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => {
506        console.info(xOffset + ' ' + yOffset)
507      })
508      .onScrollEdge((side: Edge) => {
509        console.info('To the edge')
510      })
511      .onScrollStop(() => {
512        console.info('Scroll Stop')
513      })
514      Text("上次触发的回调(Pause/Start):" + this.preCallBack)
515        .margin({ top: 60, left: 20 })
516    }.width('100%').height('100%').backgroundColor(0xDCDCDC)
517  }
518}
519```
520
521![imageAnimatorMonitorInvisibleAreaExample](figures/imageAnimatorMonitorInvisibleArea.gif)
522