vue-eaf-player
v0.1.1
Published
Espressif EAF Player for Vue
Readme
vue-eaf-player
A Vue 3 component for previewing Espressif EAF/AAF animation files with high performance and flexible parsing APIs.
EAF is a high-performance animated image format designed for Espressif chips. Visit the esp_emote_gfx repository and ESP Registry for more information.
Installation
pnpm add vue-eaf-player
# or
npm i vue-eaf-playerQuick Start
Vue Component
<template>
<div>
<!-- Display at original resolution -->
<EafPlayer :src="buffer" :fps="15" />
<!-- Or apply CSS sizing (behaves like <img>) -->
<EafPlayer :src="buffer" style="max-width: 500px;" />
<!-- Fixed container with aspect ratio preserved -->
<EafPlayer :src="buffer" style="width: 400px; height: 300px;" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { EafPlayer } from 'vue-eaf-player'
const buffer = ref<ArrayBuffer | null>(null)
async function loadFile(file: File) {
buffer.value = await file.arrayBuffer()
}
</script>Props
| Prop | Type | Default | Description |
| ------------------ | ----------------------------------- | ------- | ------------------------------------------------------ |
| src | ArrayBuffer \| Uint8Array \| null | - | EAF file data |
| fps | number | 15 | Playback frame rate |
| isLoop | boolean | true | Loop playback |
| autoPlay | boolean | true | Start playing on load |
| keepAspectRatio | boolean | true | Preserve aspect ratio when scaling |
| forceNaturalSize | boolean | false | Force display at original resolution (ignore CSS size) |
Examples:
<!-- Natural size (no CSS constraints) -->
<EafPlayer :src="buffer" />
<!-- Fixed size with aspect ratio preserved -->
<EafPlayer :src="buffer" style="width: 400px; height: 300px;" />
<!-- Max width constraint -->
<EafPlayer :src="buffer" style="max-width: 500px;" />
<!-- Stretch to fill (no aspect ratio) -->
<EafPlayer :src="buffer" :keepAspectRatio="false" style="width: 100%; height: 100%;" />Events
| Event | Payload | Description |
| -------- | ----------------------------------- | ------------------------ |
| loaded | { width, height, frames } | File loaded successfully |
| frame | { index, total } | Frame changed |
| status | { status: 'playing' \| 'paused' } | Playback status changed |
| error | EafErrorEvent | Error occurred |
Methods
Access via ref:
<script setup>
const playerRef = ref(null)
// Control playback
playerRef.value?.play()
playerRef.value?.pause()
playerRef.value?.seek(frameIndex)
// Get info
playerRef.value?.getSrcSize() // { width, height }
playerRef.value?.getFrameCount()
playerRef.value?.getCurrentFrame()
playerRef.value?.getPlayStatus() // 'playing' | 'paused'
</script>Staged Parsing API
The library provides flexible APIs for different use cases:
1. Metadata Only
Extract file metadata without parsing frames:
import { parseFileMetadata } from "vue-eaf-player";
const metadata = parseFileMetadata(arrayBuffer);
console.log(metadata);
// {
// version: 'EAF',
// frameCount: 30,
// checksum: 1234567890,
// combinedLength: 102400
// }2. File Validation
Validate file integrity without full rendering:
import { validateEafFile } from "vue-eaf-player";
const result = validateEafFile(arrayBuffer);
if (result.valid) {
console.log("File is valid!", result.metadata);
} else {
console.error("Validation errors:", result.errors);
}3. Parse to Blocks
Parse file structure without decompression:
import { parseFile } from "vue-eaf-player";
const eafFile = parseFile(arrayBuffer, (error) => {
console.warn("Non-fatal error:", error);
});
console.log(`${eafFile.frames.length} frames`);
console.log(
`Resolution: ${eafFile.frames[0].metadata.width}x${
eafFile.frames[0].metadata.height
}`,
);
console.log(`Bit depth: ${eafFile.frames[0].metadata.bitDepth}`);4. Render Specific Frames
Render only the frames you need:
import { parseFile, renderFrameToCanvas } from "vue-eaf-player";
const eafFile = parseFile(arrayBuffer);
// Render first frame only
const firstFrameCanvas = await renderFrameToCanvas(eafFile.frames[0]);
document.body.appendChild(firstFrameCanvas);
// Blocks cache decompressed data internally
// Second render is faster (uses cache)
const sameCanvas = await renderFrameToCanvas(eafFile.frames[0]);5. Full Playback
Pre-render all frames for smooth playback:
import { parseAndRenderAllFrames } from "vue-eaf-player";
const canvases = await parseAndRenderAllFrames(arrayBuffer, (error) => {
console.warn("Non-fatal error:", error);
});
// All frames are pre-rendered Canvas elements
// Use for animation loops (zero decode overhead during playback)
let currentFrame = 0;
setInterval(() => {
ctx.clearRect(0, 0, width, height);
ctx.drawImage(canvases[currentFrame], 0, 0);
currentFrame = (currentFrame + 1) % canvases.length;
}, 1000 / 15);TypeScript
Full type definitions included:
import type {
EafBlock,
EafErrorEvent,
EafFile,
EafFileMetadata,
EafFrame,
EafFrameMetadata,
EafImageBlock,
EafValidationResult,
EafVersion,
} from "vue-eaf-player";Migration from v0.0.1
Breaking Changes
The main parseEaf API has changed:
Before (v0.0.1):
const result = await parseEaf(buffer);
// Returns frames as HTMLCanvasElement[]After (v0.1.0):
// For Vue component: no changes needed
// For direct API: use new staged APIs
const canvases = await parseAndRenderAllFrames(buffer);
// Or use parseFile for more controlLegacy Compatibility
The old parseEaf function is still available but deprecated:
import { parseEaf } from "vue-eaf-player";
const result = await parseEaf(buffer);
// Still works, but consider migrating to new APIs