---
title: "useFrameIcon"
description: "Low-level primitive that registers a frame-animated StyleImageInterface icon, handling style reload re-registration and missing-image fallback."
canonical_url: "https://mapbox.mhaibaraai.cn/en/docs/composables/use-frame-icon"
---
# useFrameIcon

> Low-level primitive that registers a frame-animated StyleImageInterface icon, handling style reload re-registration and missing-image fallback.

## Introduction

`useFrameIcon` is the low-level primitive for frame-animated icons: it registers an array of per-frame `ImageData` objects as a `StyleImageInterface`, cycling through them at a fixed `fps` or per-frame `durations`, and automatically handles style-reload re-registration, `styleimagemissing` fallback, and cleanup on unmount. Both [MapboxSpriteImage](https://mapbox.mhaibaraai.cn/docs/effects/sprite-image) and [MapboxAnimatedImage](https://mapbox.mhaibaraai.cn/docs/effects/animated-image) are built on top of it.

> [!NOTE]
> 
> Must be called inside a 
> 
> <MapboxMap>
> 
>  subtree (relies on 
> 
> useMap
> 
>  internally). 
> 
> frames
> 
>  and 
> 
> durations
> 
>  are getter functions — returning updated values takes effect immediately, making it straightforward to fill them after async decoding. For most use cases, the SpriteImage or AnimatedImage components are sufficient; this primitive is only needed when you have a custom frame source.

## Usage

A child component draws a pulsing ring frame by frame on a canvas and registers it as a symbol icon via `useFrameIcon`:

```vue [UseFrameIconExample.vue]
<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap :options="{ style: 'mapbox://styles/mapbox/dark-v11', center: [116.397, 39.908], zoom: 13 }">
      <UseFrameIconLayerExample />
    </MapboxMap>
  </div>
</template>
```

Child component implementation (must be inside a `<MapboxMap>` subtree):

```vue
<script setup lang="ts">
import type { FeatureCollection } from 'geojson'

const size = 64
const FRAME_COUNT = 30
const data: FeatureCollection = {
  type: 'FeatureCollection',
  features: [{ type: 'Feature', properties: {}, geometry: { type: 'Point', coordinates: [116.397, 39.908] } }]
}

function buildFrames(): ImageData[] {
  const canvas = document.createElement('canvas')
  canvas.width = size
  canvas.height = size
  const context = canvas.getContext('2d')!
  return Array.from({ length: FRAME_COUNT }, (_, i) => {
    const t = i / FRAME_COUNT
    context.clearRect(0, 0, size, size)
    context.beginPath()
    context.arc(size / 2, size / 2, (size / 2 - 3) * t, 0, Math.PI * 2)
    context.strokeStyle = `rgba(34, 211, 238, ${1 - t})`
    context.lineWidth = 3
    context.stroke()
    return context.getImageData(0, 0, size, size)
  })
}

const { map } = useMap()
const frames = ref<ImageData[]>([])
onMounted(() => {
  frames.value = buildFrames()
  map.value?.triggerRepaint()
})

useFrameIcon({ imageName: 'pulse-ring', size, frames: () => frames.value, fps: 24 })
</script>

<template>
  <MapboxSource source-id="pulse-pts" :source="{ type: 'geojson', data }">
    <MapboxLayer layer-id="pulse-pts" type="symbol" source="pulse-pts" :layout="{ 'icon-image': 'pulse-ring', 'icon-allow-overlap': true }" />
  </MapboxSource>
</template>
```

## API

### `useFrameIcon()`

Registers a frame-animated icon. No return value (side-effect only).

**options.imageName** (`string`) *required*: The name to register in the style (referenced by icon-image in symbol layers).

**options.size** (`number`) *required*: Texture dimension in pixels (width and height).

**options.frames** (`() => ImageData[]`) *required*: Getter for the current frame sequence (reactive).

**options.fps** (`number`): Fixed frame rate; used when durations is not provided.

**options.durations** (`() => number[] | undefined`): Per-frame duration in ms (reactive getter); takes priority over fps.

## Changelog

See commit history for [src/runtime/composables/useFrameIcon.ts](https://github.com/mhaibaraai/movk-mapbox/commits/main/src/runtime/composables/useFrameIcon.ts).


## Sitemap

See the full [sitemap](https://mapbox.mhaibaraai.cn/sitemap.md) for all pages.
