Skip to main content
This example demonstrates how to build a Helios composition using Vue 3. It showcases Vue-specific patterns including composables for frame synchronization and reactive template bindings.

Setup

Install Helios core and Vue dependencies:
npm install @helios-project/core vue

Implementation

Composable for frame synchronization

Create a composable to subscribe to Helios frame updates:
// composables/useVideoFrame.ts
import { ref, onUnmounted, type Ref } from 'vue';
import type { Helios } from '@helios-project/core';

export function useVideoFrame(helios: Helios): Ref<number> {
    const frame = ref(helios.getState().currentFrame);

    const update = (state: { currentFrame: number }) => {
        frame.value = state.currentFrame;
    };

    const unsubscribe = helios.subscribe(update);

    onUnmounted(() => {
        unsubscribe();
    });

    return frame;
}
The composable uses Vue’s ref to create a reactive frame reference and onUnmounted to handle cleanup when the component is destroyed.

Main component

Build your composition using Vue’s template syntax and the useVideoFrame composable:
<!-- App.vue -->
<script setup lang="ts">
import { Helios } from '@helios-project/core';
import { useVideoFrame } from './composables/useVideoFrame';

// Initialize Helios singleton
const duration = 5;
const fps = 30;
const helios = new Helios({ duration, fps });
helios.bindToDocumentTimeline();

// Expose to window for debugging/player control
if (typeof window !== 'undefined') {
    (window as any).helios = helios;
}

const frame = useVideoFrame(helios);
</script>

<template>
  <div class="container">
    <div
        class="box"
        :style="{
            opacity: Math.min(1, frame / 30),
            transform: `scale(${Math.min(1.5, 0.5 + frame / 150)}) rotate(${frame * 2}deg)`
        }"
    >
        Vue DOM
    </div>
    <div class="info">Frame: {{ frame.toFixed(2) }}</div>
  </div>
</template>

<style scoped>
.container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: white;
    font-family: sans-serif;
}
.box {
    width: 200px;
    height: 200px;
    background-color: #42b883;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    font-weight: bold;
    border-radius: 20px;
    box-shadow: 0 0 20px rgba(66, 184, 131, 0.5);
    border: 4px solid #35495e;
}
.info {
    margin-top: 2rem;
    font-size: 1.5rem;
}
</style>

Key Vue patterns

Composable-based state management

The useVideoFrame composable encapsulates Helios subscription logic using Vue’s Composition API. It returns a reactive ref that automatically triggers re-renders when the frame changes.

Dynamic style bindings

Use Vue’s :style binding to apply dynamic animations. Calculations happen in the template, keeping the component concise and reactive.

Script setup syntax

The <script setup> syntax provides a clean, TypeScript-friendly way to define component logic without boilerplate. Variables and imports are automatically available in the template.

Scoped styles

Scoped styles ensure CSS only applies to this component, preventing style leakage while maintaining clean separation between logic and presentation.

Usage

Run the development server:
npm run dev
The composition will render with reactive frame updates. The Helios instance is exposed on window.helios for debugging and player control.

Build docs developers (and LLMs) love