JSPM

  • Created
  • Published
  • Downloads 66
  • Score
    100M100P100Q57577F
  • License MIT

A React package for 3D avatar animations with customizable GLB models and actions

Package Exports

  • ryd-avatar
  • ryd-avatar/dist/index.cjs.js
  • ryd-avatar/dist/index.esm.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ryd-avatar) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

RYD Avatar

A powerful React package for 3D avatar animations with customizable GLB models and dynamic actions.

Features

  • 🎭 3D Avatar Rendering: High-quality 3D avatar rendering using Three.js
  • 🎬 Custom Animations: Support for custom GLB models and animations
  • 🔧 Dynamic Actions: Add, remove, and modify avatar actions at runtime
  • 🎮 Easy Integration: Simple React components and hooks
  • 🎨 Customizable: Full control over lighting, camera, and styling
  • 📱 Responsive: Works on desktop and mobile devices
  • 🎤 TTS Integration: Built-in support for text-to-speech synchronization
  • 📦 Lightweight: Minimal package size - you provide your own GLB files

Installation

npm install ryd-avatar

Quick Start

⚠️ Important: You need to provide your own GLB files. See the GLB Setup Guide for detailed instructions.

import React, { useEffect } from 'react';
import { RYDAvatar, AvatarProvider, useAvatar } from 'ryd-avatar';

function App() {
  const { addAction, playAction, playSound } = useAvatar();

  useEffect(() => {
    // Add your GLB files with semantic presets - much easier!
    addAction('idle', {
      model: '/assets/idle.glb',
      animationIndex: 0,
      loop: true,
      speed: 'normal',        // 'slow', 'normal', 'fast', 'very-fast', 'super-fast'
      scale: 'large',         // 'tiny', 'small', 'medium', 'large', 'xlarge', 'huge'
      position: 'center',     // 'center', 'left', 'right', 'top', 'bottom', 'floating', 'grounded'
      rotation: 'front-slight', // 'front', 'left', 'right', 'back', 'tilted', 'dynamic'
      autoPlaySound: false
    });

    addAction('talking', {
      model: '/assets/talking.glb',
      animationIndex: 0,
      loop: true,
      speed: 'fast',
      scale: 'large',
      position: 'center',
      rotation: 'front-slight',
      sound: '/assets/tts-audio.mp3', // Your TTS audio file
      autoPlaySound: true,
      soundVolume: 0.8,
      soundDelay: 0
    });
  }, [addAction]);

  const handleTTS = (text) => {
    // Your TTS implementation
    const audioUrl = generateTTS(text); // Your TTS function
    playAction('talking', audioUrl); // Play action with custom sound
  };

  return (
    <AvatarProvider>
      {/* Use size presets for easy responsive design */}
      <RYDAvatar size="main" lighting="soft" />
      {/* Control via functions - no UI buttons included */}
      <button onClick={() => playAction('idle')}>Idle</button>
      <button onClick={() => handleTTS('Hello, how are you?')}>Speak</button>
    </AvatarProvider>
  );
}

🎨 Developer-Friendly Semantic Presets

The package now uses semantic words instead of numbers, making it much easier to customize and use!

Size Presets

// Container sizes - perfect for responsive design
<RYDAvatar size="icon-small" />    // 64x64px - for buttons, icons
<RYDAvatar size="card" />          // 200x250px - for cards, sidebars  
<RYDAvatar size="main" />          // 400x500px - for main content
<RYDAvatar size="hero" />          // 600x700px - for hero sections
<RYDAvatar size="mobile" />        // 280x350px - mobile optimized
<RYDAvatar size="tablet" />        // 400x500px - tablet optimized
<RYDAvatar size="desktop" />       // 600x700px - desktop optimized

Position Presets

addAction('idle', {
  position: 'center',        // Perfect center placement
  // position: 'left',       // Left side
  // position: 'right',      // Right side  
  // position: 'top',        // Top placement
  // position: 'bottom',     // Bottom placement
  // position: 'floating',   // Floating above ground
  // position: 'grounded',   // Grounded placement
});

Scale Presets

addAction('idle', {
  scale: 'tiny',     // 0.5x - very small
  scale: 'small',    // 0.8x - small
  scale: 'medium',   // 1.0x - normal size
  scale: 'large',    // 1.5x - large (default)
  scale: 'xlarge',   // 2.0x - extra large
  scale: 'huge',     // 3.0x - huge
});

Speed Presets

addAction('dance', {
  speed: 'slow',        // 0.5x - slow motion
  speed: 'normal',      // 1.0x - normal speed
  speed: 'fast',        // 1.5x - fast
  speed: 'very-fast',   // 2.0x - very fast
  speed: 'super-fast',  // 3.0x - super fast
});

Rotation Presets

addAction('hello', {
  rotation: 'front',        // Facing forward
  rotation: 'left',         // Facing left
  rotation: 'right',        // Facing right
  rotation: 'back',         // Facing back
  rotation: 'tilted',       // Slightly tilted
  rotation: 'dynamic',      // Dynamic movement
  rotation: 'front-slight', // Front with slight tilt
  rotation: 'front-up',     // Front looking up
  rotation: 'front-down',   // Front looking down
});

Lighting Presets

<RYDAvatar lighting="bright" />    // Bright, well-lit
<RYDAvatar lighting="soft" />      // Soft, gentle lighting (default)
<RYDAvatar lighting="dramatic" />  // Dramatic shadows
<RYDAvatar lighting="minimal" />   // Minimal lighting

Function-Based Control

The package is designed to be controlled entirely via functions - no UI buttons are included. This gives you complete control over when and how actions are triggered.

Available Functions

const {
  // Action control
  playAction,    // Play an action with optional custom sound
  stopAction,    // Stop current action and sound
  pauseAction,   // Pause current action and sound
  resumeAction,  // Resume paused action and sound
  
  // Sound control
  playSound,     // Play custom sound
  stopSound,     // Stop current sound
  
  // Action management
  addAction,     // Add new action
  removeAction,  // Remove action
  updateAction,  // Update existing action
  
  // State
  currentState,  // Current action state
  isPlaying,     // Whether animation is playing
  actions        // All available actions
} = useAvatar();

Sound & TTS Support

The package includes built-in sound support for TTS integration:

Action Configuration with Sound

addAction('talking', {
  model: '/assets/talking.glb',
  animationIndex: 0,
  loop: true,
  speed: 1.2,
  scale: 1.5,
  position: [0, -1.5, 0],
  rotation: [-0.1, 0, 0],
  
  // Sound configuration
  sound: '/assets/default-tts.mp3',  // Default sound file
  autoPlaySound: true,               // Auto-play when action starts
  soundVolume: 0.8,                  // Volume (0-1)
  soundDelay: 0                      // Delay before playing (ms)
});

Custom TTS Integration

const handleTTS = async (text) => {
  // Generate TTS audio (your implementation)
  const audioUrl = await generateTTS(text);
  
  // Play action with custom TTS audio
  playAction('talking', audioUrl);
};

// Or play sound independently
const playCustomSound = (audioUrl) => {
  playSound(audioUrl, 0.8, 100); // volume: 0.8, delay: 100ms
};

🚀 Easy Customization Examples

Small Avatar for Buttons

<RYDAvatar size="icon-small" lighting="bright" />

Large Avatar for Hero Section

<RYDAvatar size="hero" lighting="dramatic" />

Responsive Avatar

<RYDAvatar 
  size="mobile"  // Automatically adjusts for mobile
  lighting="soft" 
/>

Custom Action with Semantic Presets

addAction('celebration', {
  model: '/assets/celebration.glb',
  animationIndex: 0,
  loop: false,
  speed: 'fast',           // Fast celebration
  scale: 'xlarge',         // Big celebration
  position: 'floating',    // Floating in air
  rotation: 'dynamic',     // Dynamic movement
  sound: '/assets/celebration.mp3',
  autoPlaySound: true
});

Multiple Avatars for Different Use Cases

// Small avatar for navigation
<RYDAvatar size="icon-medium" />

// Medium avatar for sidebar
<RYDAvatar size="sidebar" lighting="minimal" />

// Large avatar for main content
<RYDAvatar size="main" lighting="soft" />

// Hero avatar for landing page
<RYDAvatar size="hero" lighting="dramatic" />

Default Action Types

The package provides these default action types (you provide the GLB files):

  • idle - Default waiting/idle animation
  • talking - Animation for text-to-speech (with sound support)
  • hello - Wave/greeting animation
  • dance - Dancing animation
  • celebration - Celebration/cheering animation
  • disappointment - Sad/disappointed animation
  • push - Pushing gesture animation
  • waiting - Waiting animation

Basic Usage

Simple Avatar

import React from 'react';
import { RYDAvatar, AvatarProvider } from 'ryd-avatar';

const MyAvatar = () => {
  return (
    <AvatarProvider>
      <div style={{ width: '600px', height: '700px' }}>
        <RYDAvatar />
      </div>
    </AvatarProvider>
  );
};

Custom Actions

import React from 'react';
import { RYDAvatar, AvatarProvider } from 'ryd-avatar';

const customActions = {
  // Override default action
  dance: {
    model: '/path/to/your/custom-dance.glb',
    animationIndex: 0,
    loop: true,
    speed: 1.2,
    scale: 1.5,
    position: [0, -1.5, 0],
    rotation: [-0.1, 0, 0],
    label: 'Custom Dance',
    icon: '💃',
    color: 'purple'
  },
  // Add new action
  yoga: {
    model: '/path/to/your/yoga.glb',
    animationIndex: 0,
    loop: true,
    speed: 0.8,
    scale: 1.5,
    position: [0, -1.5, 0],
    rotation: [-0.1, 0, 0],
    label: 'Yoga',
    icon: '🧘',
    color: 'green'
  }
};

const CustomAvatar = () => {
  return (
    <AvatarProvider customActions={customActions}>
      <RYDAvatar />
    </AvatarProvider>
  );
};

Controlled Avatar

import React from 'react';
import { RYDAvatar, AvatarProvider, useAvatar } from 'ryd-avatar';

const ControlledAvatar = () => {
  const { playAction, currentState, getAvailableActions } = useAvatar();

  return (
    <div>
      <RYDAvatar />
      
      <div>
        <h3>Available Actions:</h3>
        {getAvailableActions().map(action => (
          <button
            key={action}
            onClick={() => playAction(action)}
            style={{
              backgroundColor: currentState === action ? '#007bff' : '#f8f9fa',
              color: currentState === action ? 'white' : 'black',
              padding: '10px',
              margin: '5px',
              border: '1px solid #dee2e6',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            {action}
          </button>
        ))}
      </div>
    </div>
  );
};

const App = () => {
  return (
    <AvatarProvider>
      <ControlledAvatar />
    </AvatarProvider>
  );
};

API Reference

Components

RYDAvatar

The main avatar component.

Props:

  • className (string): Custom CSS class
  • style (object): Custom styles
  • width (number): Container width (default: 600)
  • height (number): Container height (default: 700)
  • enableShadows (boolean): Enable contact shadows (default: true)
  • enableLights (boolean): Enable default lighting (default: true)
  • camera (object): Camera configuration
  • lighting (object): Custom lighting configuration

AvatarProvider

Context provider for avatar state management.

Props:

  • children (ReactNode): Child components
  • customActions (object): Custom action configurations
  • defaultState (string): Default avatar state
  • onStateChange (function): Callback when state changes
  • onAnimationComplete (function): Callback when animation completes

Hooks

useAvatar()

Hook for controlling avatar actions and state.

Returns:

  • currentState (string): Current avatar state
  • isPlaying (boolean): Whether animation is playing
  • actions (object): Available actions
  • setState (function): Set avatar state
  • setPlaying (function): Set playing state
  • playAction (function): Play specific action
  • stopAction (function): Stop current action
  • pauseAction (function): Pause current action
  • resumeAction (function): Resume current action
  • addAction (function): Add new action
  • removeAction (function): Remove action
  • updateAction (function): Update existing action
  • hasAction (function): Check if action exists
  • getCurrentAction (function): Get current action config
  • getAvailableActions (function): Get all available actions

Action Configuration

Each action is configured with the following properties:

{
  model: string,           // Path to GLB model file
  animationIndex: number,  // Index of animation in GLB file
  loop: boolean,          // Whether animation should loop
  speed: number,          // Animation speed multiplier
  scale: number,          // Model scale
  position: [x, y, z],    // Model position
  rotation: [x, y, z],    // Model rotation
  label: string,          // Display label
  icon: string,           // Emoji or icon
  color: string           // Color theme
}

Default Actions

The package comes with these default actions:

  • idle: Default idle animation
  • talking: Talking animation for TTS
  • hello: Hello/wave animation
  • dance: Dance animation
  • celebration: Celebration animation
  • disappointment: Disappointment animation
  • push: Push animation
  • waiting: Waiting animation

Advanced Usage

Dynamic Action Management

const { addAction, removeAction, updateAction } = useAvatar();

// Add new action
addAction('yoga', {
  model: '/path/to/yoga.glb',
  animationIndex: 0,
  loop: true,
  speed: 0.8,
  scale: 1.5,
  position: [0, -1.5, 0],
  rotation: [-0.1, 0, 0],
  label: 'Yoga',
  icon: '🧘',
  color: 'green'
});

// Update existing action
updateAction('dance', { speed: 1.5, scale: 2.0 });

// Remove action
removeAction('yoga');

Text-to-Speech Integration

const { playAction, setPlaying } = useAvatar();

const speak = (text) => {
  playAction('talking');
  setPlaying(true);

  const utterance = new SpeechSynthesisUtterance(text);
  utterance.onend = () => {
    playAction('idle');
    setPlaying(false);
  };

  speechSynthesis.speak(utterance);
};

Custom Styling

<RYDAvatar
  width={800}
  height={600}
  className="my-avatar"
  style={{
    border: '2px solid #007bff',
    borderRadius: '10px',
    boxShadow: '0 4px 8px rgba(0,0,0,0.1)'
  }}
  enableShadows={true}
  enableLights={true}
  camera={{ position: [0, 2, 8], fov: 40 }}
  lighting={{
    ambient: { intensity: 0.8 },
    directional: { position: [5, 5, 5], intensity: 2.0 },
    spot: { position: [0, 10, 5], angle: 0.2, penumbra: 0.5, intensity: 1.0 }
  }}
/>

Requirements

  • React 16.8.0, 17.x, 18.x, or 19.x
  • Three.js compatible browser
  • WebGL support

React 19 Compatibility

This package supports React 19, but please note:

  • @react-three/drei and @react-three/fiber may show version warnings with React 19
  • These warnings are cosmetic and don't affect functionality
  • The package works correctly with React 19 despite the warnings

Dependencies

  • @react-three/fiber: React renderer for Three.js
  • @react-three/drei: Useful helpers for react-three-fiber
  • three: 3D graphics library

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For support, please open an issue on GitHub or contact the RYD team.