Rive JS API
NOT YET IMPLEMENTED.
Setup;
A global registry to track Rive instances by ID
Ref forwarding in components to expose Rive instance methods
A manager class that provides the external API
Props for ID so components can be registered
What It Would Look Like
1. Global Rive Manager (similar to MediaPlayerManager)
// RiveManager.ts
class RiveManager {
private instances: Map<string, any> = new Map();
register(id: string, riveInstance: any) {
this.instances.set(id, riveInstance);
}
unregister(id: string) {
this.instances.delete(id);
}
// Artboard control
setArtboard(id: string, artboardName: string): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
try {
instance.artboard = artboardName;
return true;
} catch (error) {
console.error(`Failed to set artboard for ${id}:`, error);
return false;
}
}
// State machine control
setStateMachine(id: string, stateMachineName: string): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
try {
instance.stateMachineName = stateMachineName;
return true;
} catch (error) {
console.error(`Failed to set state machine for ${id}:`, error);
return false;
}
}
// Input control (the powerful one)
setInput(id: string, inputName: string, value: number | boolean): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
try {
const input = instance.stateMachineInputs(instance.stateMachineName)
?.find((i: any) => i.name === inputName);
if (!input) {
console.warn(`Input "${inputName}" not found`);
return false;
}
input.value = value;
return true;
} catch (error) {
console.error(`Failed to set input for ${id}:`, error);
return false;
}
}
// Trigger control
fireTrigger(id: string, triggerName: string): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
try {
const trigger = instance.stateMachineInputs(instance.stateMachineName)
?.find((i: any) => i.name === triggerName && i.type === 'trigger');
if (!trigger) return false;
trigger.fire();
return true;
} catch (error) {
console.error(`Failed to fire trigger for ${id}:`, error);
return false;
}
}
// Playback control
play(id: string): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
instance.play();
return true;
}
pause(id: string): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
instance.pause();
return true;
}
reset(id: string): boolean {
const instance = this.instances.get(id);
if (!instance) return false;
instance.reset();
return true;
}
// Utility
getInstanceIds(): string[] {
return Array.from(this.instances.keys());
}
getInstance(id: string): any | null {
return this.instances.get(id) || null;
}
}
// Global singleton
export const riveManager = new RiveManager();
// Add to window for external access
declare global {
interface Window {
riveManager: RiveManager;
}
}
if (typeof window !== 'undefined') {
window.riveManager = riveManager;
}2. Updated Component (RiveWebGL2.tsx)
3. Webflow Props Declaration
Usage Examples
In Webflow Designer:
Add RiveWebGL2 component
Set ID to
"character-animation"Configure artboard, state machine, etc.
External JavaScript Control:
Event-Driven Example:
Real-World Use Cases
1. Interactive Character Selection
2. Progress/Loading States
3. Form Validation Feedback
Advanced: Type-Safe API
For even better DX, you could add TypeScript interfaces:
Key Considerations
1. ID Uniqueness: Just like your audio players, ensure IDs are unique across the page
2. Timing: The API only works after components mount. Consider:
3. Error Handling: The manager returns boolean for success/failure - check these!
4. Performance: Direct Rive API access is synchronous and fast
5. Webflow Compatibility: Works perfectly in published Webflow sites via custom code embeds
Would you like me to implement this Rive manager system for you? It would follow the same pattern as your existing MediaPlayerManager.
Last updated