UNPKG

rlottie-wasm-vue-player

Version:

A Vue 3 component for the rlottie-wasm animation player

589 lines (490 loc) 16.4 kB
# Rlottie WASM Vue Player A Vue 3 component for the rlottie-wasm animation player. This package allows you to play Lottie animations in your Vue applications using the rlottie WebAssembly module. ## Improved Usage Experience With this package, you can enjoy a seamless and efficient experience when working with Lottie animations in your Vue applications. The key benefits include: - **Zero configuration required** - All WASM and JS assets are automatically included - **Simple import** - Just `import { RlottiePlayer } from 'rlottie-vue-player'` and you're ready to go - Play, pause, stop, and seek Lottie animations - Control playback speed - Customize layer colors, opacity, position, scale, and rotation - Responsive design - Event handling for animation lifecycle ## Installation ```bash npm install rlottie-wasm-vue-player ``` ## Setup ### 1. Install the package Install the package using npm or yarn: ```bash npm install rlottie-wasm-vue-player # or yarn add rlottie-wasm-vue-player ``` That's it! No need to manually copy any files. All required WASM and JS assets are automatically included in the package. ### 2. Import and use the component No additional script loading is required. All necessary WASM and JS files are automatically loaded when you import the component. ## Usage ### Register as a Vue plugin (global component) ```js // main.js import { createApp } from 'vue'; import App from './App.vue'; import RlottieVuePlayer from 'rlottie-wasm-vue-player'; const app = createApp(App); // Register the plugin with optional configuration app.use(RlottieVuePlayer, { // Optional: custom path to WASM assets if you need to override the default // wasmPath: '/custom-path' }); app.mount('#app'); ``` ### Use as a local component ```js // YourComponent.vue import { RlottiePlayer } from 'rlottie-wasm-vue-player'; export default { components: { RlottiePlayer } }; ``` ### Basic Example ```vue <template> <RlottiePlayer :src="BirthdayCake" :autoplay="true" :loop="true" :speed="1" /> </template> <script setup> import { RlottiePlayer } from 'rlottie-wasm-vue-player'; import BirthdayCake from 'somewhere/BirthdayCakeColorful.json'; </script> ``` ### Comprehensive Example of Usage Pattern ```vue <template> <div class="lottie-demo"> <h1>Lottie Animation Player Demo</h1> <!-- Animation Player --> <section class="player-section"> <div class="player-display"> <RlottiePlayer ref="player" :src="animationData" :width="displaySize.width" :height="displaySize.height" :autoplay="playbackSettings.autoplay" :loop="playbackSettings.loop" :speed="playbackSettings.speed" :layers="layerCustomizations" @load="onAnimationLoaded" @play="isPlaying = true" @pause="isPlaying = false" @stop="isPlaying = false" @error="onAnimationError" @complete="onAnimationComplete" /> </div> <!-- Basic Playback Controls --> <div class="control-panel"> <h2>Playback Controls</h2> <div class="control-buttons"> <button class="control-btn" @click="playAnimation" :disabled="isPlaying">Play</button> <button class="control-btn" @click="pauseAnimation" :disabled="!isPlaying">Pause</button> <button class="control-btn" @click="stopAnimation">Stop</button> </div> <div class="progress-control"> <label> <span>Progress: {{ progressValue }}%</span> <input type="range" min="0" max="100" v-model.number="progressValue" @input="seekToPosition" /> </label> </div> <div class="speed-control"> <label> <span>Speed: {{ playbackSettings.speed }}x</span> <input type="range" min="0.1" max="5" step="0.1" v-model.number="playbackSettings.speed" /> </label> </div> <div class="playback-options"> <label> <input type="checkbox" v-model="playbackSettings.autoplay" /> Autoplay </label> <label> <input type="checkbox" v-model="playbackSettings.loop" /> Loop </label> </div> </div> </section> <!-- Animation Source Controls --> <section class="source-section"> <h2>Animation Source</h2> <div class="source-controls"> <button class="source-btn" @click="loadSampleAnimation">Load Sample Animation</button> </div> <div class="paste-json"> <h4>Or paste animation JSON:</h4> <textarea v-model="jsonInput" placeholder="Paste Lottie JSON here..." rows="5" ></textarea> <button @click="loadFromJsonInput">Load JSON</button> </div> </section> <!-- Layer Customization --> <section class="customization-section" v-if="targetLayerPath"> <h2>Layer Customization</h2> <div class="layer-path-input"> <label> Layer Path: <input type="text" v-model="targetLayerPath" placeholder="e.g. Shape Layer 1" /> </label> </div> <div class="customization-panels"> <!-- Color Controls --> <div class="customization-panel"> <h3>Color</h3> <div class="color-controls"> <label> R: <input type="range" min="0" max="255" v-model.number="colorSettings.r" @input="updateLayerColor" /> <span>{{ colorSettings.r }}</span> </label> <label> G: <input type="range" min="0" max="255" v-model.number="colorSettings.g" @input="updateLayerColor" /> <span>{{ colorSettings.g }}</span> </label> <label> B: <input type="range" min="0" max="255" v-model.number="colorSettings.b" @input="updateLayerColor" /> <span>{{ colorSettings.b }}</span> </label> </div> </div> <!-- Opacity Controls --> <div class="customization-panel"> <h3>Opacity</h3> <label> <input type="range" v-model.number="opacityValue" min="0" max="1" step="0.1" @input="updateLayerOpacity" /> <span>{{ opacityValue }}</span> </label> </div> <!-- Stroke Width Controls --> <div class="customization-panel"> <h3>Stroke Width</h3> <label> <input type="range" v-model.number="strokeWidthValue" min="1" max="20" @input="updateStrokeWidth" /> <span>{{ strokeWidthValue }}</span> </label> </div> <!-- Position Controls --> <div class="customization-panel"> <h3>Position</h3> <div class="position-controls"> <label> X: <input type="number" v-model.number="positionValues.x" @change="updatePosition" /> </label> <label> Y: <input type="number" v-model.number="positionValues.y" @change="updatePosition" /> </label> </div> </div> <!-- Scale Controls --> <div class="customization-panel"> <h3>Scale</h3> <div class="scale-controls"> <label> Width: <input type="number" v-model.number="scaleValues.width" step="0.1" @change="updateScale" /> </label> <label> Height: <input type="number" v-model.number="scaleValues.height" step="0.1" @change="updateScale" /> </label> </div> </div> <!-- Rotation Controls --> <div class="customization-panel"> <h3>Rotation</h3> <label> <input type="range" v-model.number="rotationValue" min="0" max="360" @input="updateRotation" /> <span>{{ rotationValue }}°</span> </label> </div> </div> </section> <!-- Animation Properties --> <section class="properties-section" v-if="animationProperties"> <h2>Animation Properties</h2> <pre>{{ JSON.stringify(animationProperties, null, 2) }}</pre> </section> </div> </template> <script setup> import { ref, reactive, onMounted } from 'vue'; import { RlottiePlayer } from 'rlottie-wasm-vue-player'; import BirthdayCakeLottieJSON from 'src/lotties/BirthdayCakeColorful.json'; // ------------------------ // Player Configuration // ------------------------ // Reference to the player component instance const player = ref(null); // Animation data source const animationData = ref(''); const jsonInput = ref(BirthdayCakeLottieJSON); // Display dimensions const displaySize = reactive({ width: 300, height: 300 }); // Playback settings const playbackSettings = reactive({ autoplay: true, loop: true, speed: 1 }); // Playback state const isPlaying = ref(false); const progressValue = ref(0); // Animation metadata const animationProperties = ref(null); // ------------------------ // Layer Customization // ------------------------ // Target layer to customize const targetLayerPath = ref(''); // e.g., 'Shape Layer 1' // Color settings const colorSettings = reactive({ r: 255, g: 0, b: 0 }); // Other customization values const opacityValue = ref(1); const strokeWidthValue = ref(5); const positionValues = reactive({ x: 0, y: 0 }); const scaleValues = reactive({ width: 1, height: 1 }); const rotationValue = ref(0); // Collection of all layer customizations const layerCustomizations = ref({}); // ------------------------ // Playback Control Methods // ------------------------ // Start animation playback const playAnimation = () => { if (player.value) { player.value.play(); } }; // Pause animation playback const pauseAnimation = () => { if (player.value) { player.value.pause(); } }; // Stop animation and reset to first frame const stopAnimation = () => { if (player.value) { player.value.stop(); } }; // Seek to a specific position in the animation const seekToPosition = () => { if (player.value) { player.value.seek(progressValue.value); } }; // ------------------------ // Animation Loading // ------------------------ // Load a sample animation from a URL const loadSampleAnimation = () => { animationData.value = '/sample.json'; targetLayerPath.value = 'Shape Layer 1'; // Default layer path for the sample }; // Load animation from JSON input (string or object) const loadFromJsonInput = () => { if (typeof jsonInput.value === 'string') { try { // Parse string input into object animationData.value = JSON.parse(jsonInput.value); } catch (e) { alert('Invalid JSON string: ' + e.message); animationData.value = null; } } else if (typeof jsonInput.value === 'object' && jsonInput.value !== null) { // Use direct object reference animationData.value = jsonInput.value; } else { alert('JSON input is empty or invalid.'); animationData.value = null; } }; // ------------------------ // Event Handlers // ------------------------ // Called when animation is successfully loaded const onAnimationLoaded = (data) => { console.log('Animation loaded successfully:', data); updateAnimationProperties(); }; // Called when animation fails to load const onAnimationError = (error) => { console.error('Animation error:', error); alert('Failed to load animation: ' + (error.message || error)); }; // Called when animation playback completes (only if loop is false) const onAnimationComplete = () => { console.log('Animation playback complete'); isPlaying.value = false; }; // ------------------------ // Animation Properties // ------------------------ // Fetch and update animation properties from the player const updateAnimationProperties = () => { if (player.value) { animationProperties.value = player.value.getProperties(); } }; // ------------------------ // Layer Customization Methods // ------------------------ // Update layer color const updateLayerColor = () => { updateLayer({ color: { r: colorSettings.r, g: colorSettings.g, b: colorSettings.b } }); }; // Update layer opacity const updateLayerOpacity = () => { updateLayer({ opacity: opacityValue.value }); }; // Update stroke width const updateStrokeWidth = () => { updateLayer({ strokeWidth: strokeWidthValue.value }); }; // Update layer position const updatePosition = () => { updateLayer({ position: { x: positionValues.x, y: positionValues.y } }); }; // Update layer scale const updateScale = () => { updateLayer({ scale: { width: scaleValues.width, height: scaleValues.height } }); }; // Update layer rotation const updateRotation = () => { updateLayer({ rotation: rotationValue.value }); }; // Helper method to update layer customizations const updateLayer = (properties) => { if (!targetLayerPath.value) return; const path = targetLayerPath.value; const currentLayerProps = layerCustomizations.value[path] || {}; layerCustomizations.value = { ...layerCustomizations.value, [path]: { ...currentLayerProps, ...properties } }; }; // ------------------------ // Lifecycle Hooks // ------------------------ onMounted(() => { // Load the imported BirthdayCakeLottieJSON by default if (jsonInput.value) { animationData.value = jsonInput.value; } else { console.warn('Default Lottie JSON is not available.'); } }); </script> ``` ## Component Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `src` | String, Object | - | Animation source - stringified JSON or URL to JSON file | | `width` | Number, String | 300 | Width of the player | | `height` | Number, String | 300 | Height of the player | | `autoplay` | Boolean | false | Whether to autoplay the animation | | `loop` | Boolean | true | Whether to loop the animation | | `speed` | Number | 1 | Playback speed (1 is normal speed) | | `background` | String | 'transparent' | Background color | | `layers` | Object | {} | Layer customizations (see below) | | `canvasId` | String | null | Optional custom canvas ID | | `assetPath` | String | '' | Optional: Custom path to asset files (not required with default usage) | ## Layer Customization The `layers` prop accepts an object with the following format: ```js { "keypath": { color: { r: 255, g: 0, b: 0 }, opacity: 0.5, strokeWidth: 2, position: { x: 10, y: 20 }, scale: { width: 1.2, height: 0.8 }, rotation: 45 } } ``` Where `keypath` is the path to the layer in the Lottie animation (e.g., "Shape Layer 1"). ## Component Methods | Method | Description | |--------|-------------| | `play()` | Starts or resumes animation playback | | `pause()` | Pauses animation playback | | `stop()` | Stops animation and resets to the first frame | | `seek(percentage)` | Seeks to a specific frame based on percentage (0-100) | | `getProperties()` | Returns properties of the current animation | ## Global API The package also exposes a global API on `window.RlottieVuePlayer` with the following methods: | Method | Description | |--------|-------------| | `loadAnimation(jsonData)` | Loads Lottie animation data (stringified JSON) | | `play()` | Starts or resumes animation playback | | `pause()` | Pauses animation playback | | `stop()` | Stops animation and resets to the first frame | | `seek(percentage)` | Seeks to a specific frame based on percentage (0-100) | | `getAnimationProperties()` | Returns properties of the current animation | | `setPlaySpeed(speed)` | Sets the playback speed | | `resize(width, height)` | Informs the player of the canvas dimensions | | `setLayerColor(keypath, r, g, b)` | Sets the fill and stroke color of a layer | | `setLayerOpacity(keypath, opacity)` | Sets the fill and stroke opacity of a layer (0-1) | | `setStrokeWidth(keypath, width)` | Sets the stroke width of a layer | | `setPosition(keypath, x, y)` | Sets the position of a layer | | `setScale(keypath, width, height)` | Sets the scale of a layer | | `setRotation(keypath, degree)` | Sets the rotation of a layer | ## License MIT