1# ImageAnimator 2 3The **ImageAnimator** component enables images to be played a frame-by-frame basis. The list of images to be played as well as the duration of each image can be configured. 4 5> **NOTE** 6> 7> This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version. 8 9 10 11## Child Components 12 13Not supported 14 15 16## APIs 17 18ImageAnimator() 19 20**Widget capability**: This API can be used in ArkTS widgets since API version 10. 21 22**Atomic service API**: This API can be used in atomic services since API version 11. 23 24**System capability**: SystemCapability.ArkUI.ArkUI.Full 25 26## Attributes 27 28In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported. 29 30### images 31 32images(value: Array<ImageFrameInfo>) 33 34Sets the image frame information. Dynamic update is not supported. 35 36**Widget capability**: This API can be used in ArkTS widgets since API version 10. 37 38**Atomic service API**: This API can be used in atomic services since API version 11. 39 40**System capability**: SystemCapability.ArkUI.ArkUI.Full 41 42**Parameters** 43 44| Name| Type | Mandatory| Description | 45| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ | 46| value | Array<[ImageFrameInfo](#imageframeinfo)> | Yes | Image frame information. The information of each frame includes the image path, image size, image position, and image playback duration. For details, see [ImageFrameInfo](#imageframeinfo).<br>Default value: **[]**<br> **NOTE**<br>If the input array is too large, memory usage may increase. Therefore, as the controller of memory usage, be sure to assess potential memory consumption before passing in the data to avoid issues such as insufficient memory.| 47 48### state 49 50state(value: AnimationStatus) 51 52Sets the playback state of the animation. 53 54**Widget capability**: This API can be used in ArkTS widgets since API version 10. 55 56**Atomic service API**: This API can be used in atomic services since API version 11. 57 58**System capability**: SystemCapability.ArkUI.ArkUI.Full 59 60**Parameters** 61 62| Name| Type | Mandatory| Description | 63| ------ | ------------------------------------------------------- | ---- | ------------------------------------------------------------ | 64| value | [AnimationStatus](ts-appendix-enums.md#animationstatus) | Yes | Playback state of the animation. The default state is **Initial**.<br>Default value: **AnimationStatus.Initial**| 65 66### duration 67 68duration(value: number) 69 70Sets the playback duration. This attribute does not take effect when a separate duration is set for any of the image frames. 71 72**Widget capability**: This API can be used in ArkTS widgets since API version 10. 73 74**Atomic service API**: This API can be used in atomic services since API version 11. 75 76**System capability**: SystemCapability.ArkUI.ArkUI.Full 77 78**Parameters** 79 80| Name| Type | Mandatory| Description | 81| ------ | ------ | ---- | ------------------------------------------------------------ | 82| value | number | Yes | Playback duration.<br>If the value is **0**, no image is played.<br>If it is set to a negative value, the default value is used.<br>The value change takes effect only at the start of the next cycle.<br>Unit: ms<br>Default value: **1000**| 83 84### reverse 85 86reverse(value: boolean) 87 88Sets the playback direction. 89 90**Widget capability**: This API can be used in ArkTS widgets since API version 10. 91 92**Atomic service API**: This API can be used in atomic services since API version 11. 93 94**System capability**: SystemCapability.ArkUI.ArkUI.Full 95 96**Parameters** 97 98| Name| Type | Mandatory| Description | 99| ------ | ------- | ---- | ------------------------------------------------------------ | 100| value | boolean | Yes | Playback direction.<br>The value **false** indicates that images are played from the first one to the last one, and **true** indicates that images are played from the last one to the first one.<br>Default value: **false**| 101 102### fixedSize 103 104fixedSize(value: boolean) 105 106Sets whether the image size is fixed at the component size. 107 108**Widget capability**: This API can be used in ArkTS widgets since API version 10. 109 110**Atomic service API**: This API can be used in atomic services since API version 11. 111 112**System capability**: SystemCapability.ArkUI.ArkUI.Full 113 114**Parameters** 115 116| Name| Type | Mandatory| Description | 117| ------ | ------- | ---- | ------------------------------------------------------------ | 118| value | boolean | Yes | Whether the image size is fixed at the component size.<br> **true**: The image size is fixed at the component size. In this case, the width, height, top, and left attributes of the image are invalid.<br> **false**: The width, height, top, and left attributes of each image must be set separately. If the image size does not match the component size, the image will not be stretched.<br>Default value: **true**| 119 120### preDecode<sup>(deprecated)</sup> 121 122preDecode(value: number) 123 124Sets the number of images to be pre-decoded. 125 126This API is deprecated since API version 9. 127 128**System capability**: SystemCapability.ArkUI.ArkUI.Full 129 130**Parameters** 131 132| Name| Type | Mandatory| Description | 133| ------ | ------ | ---- | ------------------------------------------------------------ | 134| value | number | Yes | Number of images to be pre-decoded. For example, the value **2** indicates that two images following the currently playing one are pre-decoded.<br>Default value: **0**| 135 136### fillMode 137 138fillMode(value: FillMode) 139 140Sets the status before and after execution of the animation in the current playback direction. The status after execution of the animation is jointly determined by the **fillMode** and **reverse** attributes. For example, if **fillMode** is set to **Forwards**, the target will retain the state defined by the last keyframe encountered during execution. In this case, if **reverse** is set to **false**, the target will retain the state defined by the last keyframe encountered in the forward direction, that is, the last image; if **reverse** is set to **true**, the target will retain the state defined by the last keyframe encountered in the backward direction, that is, the first image. 141 142**Widget capability**: This API can be used in ArkTS widgets since API version 10. 143 144**Atomic service API**: This API can be used in atomic services since API version 11. 145 146**System capability**: SystemCapability.ArkUI.ArkUI.Full 147 148**Parameters** 149 150| Name| Type | Mandatory| Description | 151| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ | 152| value | [FillMode](ts-appendix-enums.md#fillmode) | Yes | Status before and after execution of the animation in the current playback direction.<br>Default value: **FillMode.Forwards**| 153 154### iterations 155 156iterations(value: number) 157 158Sets the number of times that the animation is played. 159 160**Atomic service API**: This API can be used in atomic services since API version 11. 161 162**System capability**: SystemCapability.ArkUI.ArkUI.Full 163 164**Parameters** 165 166| Name| Type | Mandatory| Description | 167| ------ | ------ | ---- | ------------------------------------------------------ | 168| value | number | Yes | Number of times that the animation is played. By default, the animation is played once. The value **-1** indicates that the animation is played for an unlimited number of times. Values less than -1 are treated as the default value. For the value is a floating-point number, it is rounded down.<br>Default value: **1**| 169 170### monitorInvisibleArea<sup>17+</sup> 171 172monitorInvisibleArea(monitorInvisibleArea: boolean) 173 174Sets whether the component should automatically pause or resume based on its visibility, using the system's [onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange) event. 175 176**Atomic service API**: This API can be used in atomic services since API version 17. 177 178**System capability**: SystemCapability.ArkUI.ArkUI.Full 179 180**Parameters** 181 182| Name| Type | Mandatory| Description | 183| ------ | ------ | ---- | ------------------------------------------------------ | 184| monitorInvisibleArea | boolean | Yes| Whether the component should automatically pause or resume based on its visibility, using the system's [onVisibleAreaChange](./ts-universal-component-visible-area-change-event.md#onvisibleareachange) event.<br> With the value **true**, when the component's [AnimationStatus](ts-appendix-enums.md#animationstatus) is Running, the component automatically pauses once it becomes invisible and resumes playback if it becomes visible again, based on the **onVisibleAreaChange** event.<br>Default value: **false**.<br> **NOTE**<br>When this parameter is dynamically changed from **true** to **false**,<br> the component will resume from its last paused state based on the current [AnimationStatus](ts-appendix-enums.md#animationstatus).<br>Changes to this property do not affect the custom [state](./ts-basic-components-imageanimator.md#state) value.| 185 186## ImageFrameInfo 187 188Provides image frame information. 189 190**Atomic service API**: This API can be used in atomic services since API version 11. 191 192**System capability**: SystemCapability.ArkUI.ArkUI.Full 193 194| Name | Type | Mandatory| Description| 195| -------- | -------------- | -------- | -------- | 196| src | string \| [Resource](ts-types.md#resource)<sup>9+</sup> \| [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md)<sup>12+</sup> | Yes | Image path. The image format can be .jpg, .jpeg, .svg, .png, .bmp, .webp, .ico, or .heif. The [Resource](ts-types.md#resource) type is supported since API version 9, and the [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md) type is supported since API version 12.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 10.| 197| width | number \| string | No | Image width. For the string type, numeric string values with optional units, for example, **"2"** or **"2px"**, are supported.<br>Default value: **0**.<br>Unit: vp.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 10. | 198| height | number \| string | No | Image height. For the string type, numeric string values with optional units, for example, **"2"** or **"2px"**, are supported.<br>Default value: **0**.<br>Unit: vp<br>**Widget capability**: This API can be used in ArkTS widgets since API version 10. | 199| top | number \| string | No | Vertical coordinate of the image relative to the upper left corner of the widget For the string type, numeric string values with optional units, for example, **"2"** or **"2px"**, are supported.<br>Default value: **0**.<br>Unit: vp<br>**Widget capability**: This API can be used in ArkTS widgets since API version 10. | 200| left | number \| string | No | Horizontal coordinate of the image relative to the upper left corner of the widget For the string type, numeric string values with optional units, for example, **"2"** or **"2px"**, are supported.<br>Default value: **0**.<br>Unit: vp<br>**Widget capability**: This API can be used in ArkTS widgets since API version 10. | 201| duration | number | No | Playback duration of each image frame, in milliseconds.<br>Default value: **0**.<br>Negative numbers are not supported. Setting negative values will cause the image to stay in the current frame for a long time, affecting normal playback. | 202 203## Events 204 205In addition to the [universal events](ts-component-general-events.md), the following events are supported. 206 207### onStart 208 209onStart(event: () => void) 210 211Triggered when the animation starts to play. 212 213**Widget capability**: This API can be used in ArkTS widgets since API version 10. 214 215**Atomic service API**: This API can be used in atomic services since API version 11. 216 217**System capability**: SystemCapability.ArkUI.ArkUI.Full 218 219### onPause 220 221onPause(event: () => void) 222 223Triggered when the animation playback is paused. 224 225**Widget capability**: This API can be used in ArkTS widgets since API version 10. 226 227**Atomic service API**: This API can be used in atomic services since API version 11. 228 229**System capability**: SystemCapability.ArkUI.ArkUI.Full 230 231### onRepeat 232 233onRepeat(event: () => void) 234 235Triggered when the animation playback is repeated. 236 237**Atomic service API**: This API can be used in atomic services since API version 11. 238 239**System capability**: SystemCapability.ArkUI.ArkUI.Full 240 241### onCancel 242 243onCancel(event: () => void) 244 245Triggered when the animation playback returns to the initial state. 246 247**Widget capability**: This API can be used in ArkTS widgets since API version 10. 248 249**Atomic service API**: This API can be used in atomic services since API version 11. 250 251**System capability**: SystemCapability.ArkUI.ArkUI.Full 252 253### onFinish 254 255onFinish(event: () => void) 256 257Triggered when the animation playback is complete or stopped. 258 259**Widget capability**: This API can be used in ArkTS widgets since API version 10. 260 261**Atomic service API**: This API can be used in atomic services since API version 11. 262 263**System capability**: SystemCapability.ArkUI.ArkUI.Full 264 265 266## Example 267 268### Example 1: Playing an Animation Using Images of the Resource Type 269 270This example demonstrates how to play an animation using the **ImageAnimator** component with images of the Resource type. 271 272```ts 273// xxx.ets 274@Entry 275@Component 276struct ImageAnimatorExample { 277 @State state: AnimationStatus = AnimationStatus.Initial; 278 @State reverse: boolean = false; 279 @State iterations: number = 1; 280 281 build() { 282 Column({ space: 10 }) { 283 ImageAnimator() 284 .images([ 285 { 286 src: $r('app.media.img1') 287 }, 288 { 289 src: $r('app.media.img2') 290 }, 291 { 292 src: $r('app.media.img3') 293 }, 294 { 295 src: $r('app.media.img4') 296 } 297 ]) 298 .duration(4000) 299 .state(this.state) 300 .reverse(this.reverse) 301 .fillMode(FillMode.None) 302 .iterations(this.iterations) 303 .width(340) 304 .height(240) 305 .margin({ top: 100 }) 306 .onStart(() => { 307 console.info('Start') 308 }) 309 .onPause(() => { 310 console.info('Pause') 311 }) 312 .onRepeat(() => { 313 console.info('Repeat') 314 }) 315 .onCancel(() => { 316 console.info('Cancel') 317 }) 318 .onFinish(() => { 319 console.info('Finish') 320 this.state = AnimationStatus.Stopped 321 }) 322 Row() { 323 Button('start').width(100).padding(5).onClick(() => { 324 this.state = AnimationStatus.Running 325 }).margin(5) 326 Button('pause').width(100).padding(5).onClick(() => { 327 this.state = AnimationStatus.Paused // Display the image of the current frame. 328 }).margin(5) 329 Button('stop').width(100).padding(5).onClick(() => { 330 this.state = AnimationStatus.Stopped // Display the image of the initial frame. 331 }).margin(5) 332 } 333 334 Row() { 335 Button('reverse').width(100).padding(5).onClick(() => { 336 this.reverse = !this.reverse 337 }).margin(5) 338 Button('once').width(100).padding(5).onClick(() => { 339 this.iterations = 1 340 }).margin(5) 341 Button('infinite').width(100).padding(5).onClick(() => { 342 this.iterations = -1 // The animation is played for an unlimited number of times. 343 }).margin(5) 344 } 345 }.width('100%').height('100%') 346 } 347} 348``` 349 350 351 352### Example 2: Playing an Animation Using Images of the PixelMap Type 353 354This example demonstrates how to play an animation using the **ImageAnimator** component with images of the PixelMap type. 355 356```ts 357// xxx.ets 358import { image } from '@kit.ImageKit'; 359 360@Entry 361@Component 362struct ImageAnimatorExample { 363 imagePixelMap: Array<PixelMap> = []; 364 @State state: AnimationStatus = AnimationStatus.Initial; 365 @State reverse: boolean = false; 366 @State iterations: number = 1; 367 @State images: Array<ImageFrameInfo> = []; 368 369 async aboutToAppear() { 370 this.imagePixelMap.push(await this.getPixmapFromMedia($r('app.media.icon'))); 371 this.images.push({ src: this.imagePixelMap[0] }); 372 } 373 374 build() { 375 Column({ space: 10 }) { 376 ImageAnimator() 377 .images(this.images) 378 .duration(2000) 379 .state(this.state) 380 .reverse(this.reverse) 381 .fillMode(FillMode.None) 382 .iterations(this.iterations) 383 .width(340) 384 .height(240) 385 .margin({ top: 100 }) 386 .onStart(() => { 387 console.info('Start'); 388 }) 389 .onPause(() => { 390 console.info('Pause'); 391 }) 392 .onRepeat(() => { 393 console.info('Repeat'); 394 }) 395 .onCancel(() => { 396 console.info('Cancel'); 397 }) 398 .onFinish(() => { 399 console.info('Finish'); 400 this.state = AnimationStatus.Stopped; 401 }) 402 Row() { 403 Button('start').width(100).padding(5).onClick(() => { 404 this.state = AnimationStatus.Running; 405 }).margin(5) 406 Button('pause').width(100).padding(5).onClick(() => { 407 this.state = AnimationStatus.Paused; // Display the image of the current frame. 408 }).margin(5) 409 Button('stop').width(100).padding(5).onClick(() => { 410 this.state = AnimationStatus.Stopped; // Display the image of the initial frame. 411 }).margin(5) 412 } 413 414 Row() { 415 Button('reverse').width(100).padding(5).onClick(() => { 416 this.reverse = !this.reverse; 417 }).margin(5) 418 Button('once').width(100).padding(5).onClick(() => { 419 this.iterations = 1; 420 }).margin(5) 421 Button('infinite').width(100).padding(5).onClick(() => { 422 this.iterations = -1; // The animation is played for an unlimited number of times. 423 }).margin(5) 424 } 425 }.width('100%').height('100%') 426 } 427 428 private async getPixmapFromMedia(resource: Resource) { 429 let unit8Array = await this.getUIContext().getHostContext()?.resourceManager?.getMediaContent({ 430 bundleName: resource.bundleName, 431 moduleName: resource.moduleName, 432 id: resource.id 433 }); 434 let imageSource = image.createImageSource(unit8Array?.buffer.slice(0, unit8Array.buffer.byteLength)); 435 let createPixelMap: image.PixelMap = await imageSource.createPixelMap({ 436 desiredPixelFormat: image.PixelMapFormat.RGBA_8888 437 }); 438 await imageSource.release(); 439 return createPixelMap; 440 } 441} 442``` 443 444 445 446### Example 3: Enabling Automatic Pause on Invisibility 447 448This example demonstrates how to use [monitorInvisibleArea](#monitorinvisiblearea17) to automatically pause the **ImageAnimator** component when it becomes invisible and resume playback when it becomes visible again. This behavior is controlled based on the component's [state](#state) being set to **AnimationStatus.Running**. 449 450```ts 451@Entry 452@Component 453struct ImageAnimatorAutoPauseTest { 454 scroller: Scroller = new Scroller(); 455 @State state: AnimationStatus = AnimationStatus.Running; 456 @State reverse: boolean = false; 457 @State iterations: number = 100; 458 @State preCallBack: string = 'Null'; 459 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 460 461 build() { 462 Stack({ alignContent: Alignment.TopStart }) { 463 Scroll(this.scroller) { 464 Column() { 465 ImageAnimator() 466 .images([ 467 { 468 src: $r('app.media.Clouds') 469 }, 470 { 471 src: $r('app.media.landscape') 472 }, 473 { 474 src: $r('app.media.sky') 475 }, 476 { 477 src: $r('app.media.mountain') 478 } 479 ]) 480 .borderRadius(10) 481 .monitorInvisibleArea(true) 482 .clip(true) 483 .duration(4000) 484 .state(this.state) 485 .reverse(this.reverse) 486 .fillMode(FillMode.Forwards) 487 .iterations(this.iterations) 488 .width(340) 489 .height(240) 490 .margin({ top: 100 }) 491 .onStart(() => { 492 this.preCallBack = "Start"; 493 console.info('ImageAnimator Start'); 494 }) 495 .onPause(() => { 496 this.preCallBack = "Pause"; 497 console.info('ImageAnimator Pause'); 498 }) 499 .onRepeat(() => { 500 console.info('ImageAnimator Repeat'); 501 }) 502 .onCancel(() => { 503 console.info('ImageAnimator Cancel'); 504 }) 505 .onFinish(() => { 506 console.info('ImageAnimator Finish'); 507 }) 508 ForEach(this.arr, (item: number) => { 509 Text(item.toString()) 510 .width('90%') 511 .height(150) 512 .backgroundColor(0xFFFFFF) 513 .borderRadius(15) 514 .fontSize(16) 515 .textAlign(TextAlign.Center) 516 .margin({ top: 10 }) 517 }, (item: string) => item) 518 }.width('100%') 519 } 520 .scrollable(ScrollDirection.Vertical) // The scrollbar scrolls in the vertical direction. 521 .scrollBar(BarState.On) // The scrollbar is always displayed. 522 .scrollBarColor(Color.Gray) // The scrollbar color is gray. 523 .scrollBarWidth(10) // The scrollbar width is 10. 524 .friction(0.6) 525 .edgeEffect(EdgeEffect.None) 526 .onWillScroll((xOffset: number, yOffset: number, scrollState: ScrollState) => { 527 console.info(xOffset + ' ' + yOffset); 528 }) 529 .onScrollEdge((side: Edge) => { 530 console.info('To the edge'); 531 }) 532 .onScrollStop(() => { 533 console.info('Scroll Stop'); 534 }) 535 536 Text("Last triggered callback (Pause/Start): " + this.preCallBack) 537 .margin({ top: 60, left: 20 }) 538 }.width('100%').height('100%').backgroundColor(0xDCDCDC) 539 } 540} 541``` 542 543 544