cinematic-renderer2d
v0.3.0
Published
High-performance, framework-agnostic NPM library that renders cinematic experiences from JSON specifications targeting 60-120fps performance
Maintainers
Readme
cinematicRenderer2D
High-performance, framework-agnostic NPM library that renders cinematic experiences from JSON specifications targeting 60-120fps performance across web frameworks.
🎮 Interactive Playground
Try it Live! - Explore examples and create your own cinematic experiences
Features
- 🚀 High Performance: Targets 60-120fps with optimized rendering backends and precompiled animations
- 🎯 Framework Agnostic: Works with React, Angular, Vue, Next.js, or plain JavaScript
- 🎨 Multiple Backends: DOM, Canvas2D rendering with future WebGL support
- 📱 Adaptive Quality: Automatic performance optimization based on device capabilities and FPS monitoring
- 🎵 Audio Integration: Synchronized audio tracks with fade effects, multi-track support, and WebAudio API
- 🔧 TypeScript: Full type safety with comprehensive interfaces and definitions
- 📦 Tree Shakeable: ESM/CJS dual output with optimized bundles and tree-shaking
- 🎭 Layer System: Extensible plugin architecture for custom visual elements
- 🎬 CLI Tools: Validation and preview tools for development workflow
- 🎥 Camera System: Viewport transformations with zoom, pan, and rotation
- 🌟 Light Layers: Cinematic lighting with radial, spot, ambient, and vignette modes
- 🔄 Scene Transitions: Smooth transitions with crossfade, slide, zoom, wipe, dissolve, and blur
- 🎨 Enhanced Animations: Looping, yoyo, keyframes, stagger effects, and randomization
- 🔊 Advanced Audio: Per-track control, fade in/out, crossfading, and multi-track mixing
- ⚡ Performance Monitor: Auto quality adjustment based on real-time FPS monitoring
- 🌫️ New Layer Types: Fog, enhanced vignette, parallax groups, and glow effects
- 🔄 State Machine: Well-defined renderer and scene states with lifecycle management
- 📦 Asset Preloader: Intelligent preloading with caching and priority loading
- 🔷 Shape Layers (NEW): Native geometric shapes (circles, rectangles, stars, polygons) with full animation support
Installation
npm install cinematic-renderer2dDocumentation
📚 Complete Documentation - Interactive documentation landing page
🎮 Live Playground - Try examples and create your own
Quick Links
- 🚀 Getting Started Guide - Installation and quick start
- 📖 API Reference - Complete API documentation
- 💡 Examples Guide - Learn from example patterns
- ⚛️ React Integration - Using with React
- 🅰️ Angular Integration - Using with Angular
- ⚡ Performance Guide - Optimization tips
- 🎓 Tutorials - Step-by-step tutorials including Shape Layers
Quick Start
Basic Usage
import { CinematicRenderer2D } from 'cinematic-renderer2d';
const renderer = new CinematicRenderer2D({
container: document.getElementById('cinematic-container'),
spec: {
schemaVersion: '1.0.0',
engine: {
targetFps: 60,
quality: 'auto',
debug: false
},
events: [{
id: 'intro',
name: 'Introduction',
scenes: ['scene1']
}],
scenes: [{
id: 'scene1',
name: 'Opening Scene',
duration: 5000,
layers: [{
id: 'background',
type: 'gradient',
zIndex: 1,
config: {
opacity: 1,
colors: ['#000000', '#333333']
},
animations: [{
property: 'opacity',
from: 0,
to: 1,
startMs: 0,
endMs: 1000,
easing: 'ease-in-out'
}]
}]
}]
}
});
// Mount and start playback
await renderer.mount();
renderer.play();
// Event handling
renderer.on('play', () => console.log('Playback started'));
renderer.on('pause', () => console.log('Playback paused'));
renderer.on('end', () => console.log('Playback completed'));// Navigation and Control
// Playback control
renderer.play();
renderer.pause();
renderer.stop();
// Navigation
renderer.seek(2500); // Seek to 2.5 seconds
renderer.goToEvent('intro');
renderer.goToScene('scene1');
// Quality control
renderer.setQuality('high'); // 'low', 'medium', 'high', 'ultra', 'auto'
// Camera control (NEW)
renderer.setCameraState({ zoom: 2.0, x: 100, y: 50, rotation: 45 });
renderer.addCameraAnimation({
property: 'zoom',
from: 1.0,
to: 2.0,
startMs: 0,
endMs: 2000,
easing: 'ease-in-out'
});
renderer.resetCamera();
// Audio control (NEW)
renderer.setMasterVolume(0.8);
const volume = renderer.getMasterVolume();
// Performance monitoring (NEW)
const fps = renderer.getCurrentFps();
const metrics = renderer.getPerformanceMetrics();
// Debug mode (NEW)
renderer.toggleDebug();
renderer.showDebug();
renderer.hideDebug();
// Cleanup
renderer.destroy();Framework Adapters
React
import { CinematicPlayer } from 'cinematic-renderer2d/react';
function App() {
const [isPlaying, setIsPlaying] = useState(false);
return (
<CinematicPlayer
spec={cinematicSpec}
autoplay={true}
onPlay={() => setIsPlaying(true)}
onPause={() => setIsPlaying(false)}
onEnd={() => setIsPlaying(false)}
onError={(error) => console.error('Playback error:', error)}
/>
);
}React Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| spec | CinematicSpec | required | JSON specification for the cinematic experience |
| autoplay | boolean | false | Start playback automatically when mounted |
| quality | QualityLevel | 'auto' | Quality level: 'low', 'medium', 'high', 'ultra', 'auto' |
| debug | boolean | false | Enable debug overlay with performance metrics |
| onPlay | () => void | - | Called when playback starts |
| onPause | () => void | - | Called when playback pauses |
| onStop | () => void | - | Called when playback stops |
| onEnd | () => void | - | Called when playback completes |
| onError | (error: Error) => void | - | Called when an error occurs |
Angular
import { CinematicPlayerComponent } from 'cinematic-renderer2d/angular';
@Component({
selector: 'app-root',
template: `
<cinematic-player
[spec]="cinematicSpec"
[autoplay]="true"
[quality]="'auto'"
[debug]="false"
(play)="onPlay()"
(pause)="onPause()"
(end)="onEnd()"
(error)="onError($event)">
</cinematic-player>
`
})
export class AppComponent {
cinematicSpec: CinematicSpec = {
// Your specification here
};
onPlay() { console.log('Playing'); }
onPause() { console.log('Paused'); }
onEnd() { console.log('Ended'); }
onError(error: Error) { console.error('Error:', error); }
}Angular Inputs/Outputs
Inputs:
spec: CinematicSpec- JSON specification (required)autoplay: boolean- Auto-start playback (default: false)quality: QualityLevel- Quality level (default: 'auto')debug: boolean- Enable debug mode (default: false)
Outputs:
play: EventEmitter<void>- Playback startedpause: EventEmitter<void>- Playback pausedstop: EventEmitter<void>- Playback stoppedend: EventEmitter<void>- Playback completederror: EventEmitter<Error>- Error occurred
JSON Specification Format
Schema Structure
interface CinematicSpec {
schemaVersion: string; // Currently '1.0.0'
engine: EngineConfig; // Engine configuration
events: CinematicEvent[]; // High-level sequences
scenes: CinematicScene[]; // Individual scenes
assets?: AssetDefinition[]; // Optional assets
}
interface EngineConfig {
targetFps?: number; // Target frame rate (default: 60)
quality?: QualityLevel; // Quality level (default: 'auto')
debug?: boolean; // Debug mode (default: false)
autoplay?: boolean; // Auto-start (default: false)
}Events and Scenes
interface CinematicEvent {
id: string; // Unique identifier
name: string; // Display name
scenes: string[]; // Scene IDs in order
transitions?: TransitionSpec[]; // Optional transitions
}
interface CinematicScene {
id: string; // Unique identifier
name: string; // Display name
duration: number; // Duration in milliseconds
layers: LayerSpec[]; // Visual layers
audio?: AudioTrackSpec[]; // Optional audio tracks
}Layers and Animations
interface LayerSpec {
id: string; // Unique identifier
type: LayerType; // Layer type (see Layer Types)
zIndex: number; // Rendering order
config: LayerConfig; // Layer-specific configuration
animations?: AnimationTrackSpec[]; // Optional animations
}
interface AnimationTrackSpec {
property: string; // Property to animate
from: any; // Starting value
to: any; // Ending value
startMs: number; // Start time in milliseconds
endMs: number; // End time in milliseconds
easing?: EasingType; // Easing function (default: 'ease')
loop?: boolean; // Loop animation (default: false)
yoyo?: boolean; // Reverse on loop (default: false)
}Layer Types
DOM Layers
Gradient Layer
{
"type": "gradient",
"config": {
"colors": ["#ff0000", "#0000ff"],
"direction": "to bottom",
"opacity": 1
}
}Image Layer
{
"type": "image",
"config": {
"src": "path/to/image.jpg",
"width": "100%",
"height": "100%",
"objectFit": "cover"
}
}Text Block Layer
{
"type": "textBlock",
"config": {
"text": "Hello World",
"fontSize": "24px",
"color": "#ffffff",
"textAlign": "center"
}
}Vignette Layer
{
"type": "vignette",
"config": {
"intensity": 0.5,
"color": "#000000",
"radius": "50%"
}
}Light Layer (NEW)
{
"type": "light",
"config": {
"mode": "spot",
"position": { "x": 50, "y": 50 },
"radius": 200,
"intensity": 0.8,
"color": "#ffffff",
"angle": 45,
"direction": 90,
"blendMode": "screen"
}
}Fog Layer (NEW)
{
"type": "fog",
"config": {
"density": 0.5,
"color": "#cccccc",
"speed": 1,
"direction": "horizontal",
"opacity": 0.7
}
}Glow Effect Layer (NEW)
{
"type": "glowEffect",
"config": {
"position": { "x": 50, "y": 50 },
"radius": 100,
"intensity": 0.8,
"color": "#ffff00",
"blur": 20
}
}Shape Layer (NEW) 🔷
{
"type": "shape",
"config": {
"shapeType": "circle",
"radius": 50,
"x": "50%",
"y": "50%",
"fillColor": "#ff6b6b",
"strokeColor": "#ffffff",
"strokeWidth": 2,
"opacity": 0.8,
"rotation": 0,
"scaleX": 1,
"scaleY": 1
}
}Supported Shape Types:
rectangle- Configurable width and heightsquare- Configurable sizecircle- Configurable radiusellipse- Configurable radiusX and radiusYtriangle- Custom verticestrapezoid- Configurable top/bottom widths and heightpolygon- Configurable sides (≥3) and radiusstar- Configurable points (≥3), inner/outer radius
All shape properties are fully animatable!
Canvas2D Layers
Particles Layer
{
"type": "particles",
"config": {
"count": 100,
"size": 2,
"color": "#ffffff",
"speed": 1,
"direction": "up"
}
}Starfield Layer
{
"type": "starfield",
"config": {
"density": 0.5,
"twinkle": true,
"colors": ["#ffffff", "#ffffcc"]
}
}Parallax Group Layer (NEW)
{
"type": "parallaxGroup",
"config": {
"layers": ["layer1", "layer2", "layer3"],
"depth": 0.5,
"scrollSpeed": 1.2
}
}Animation System
Easing Functions
Supported easing functions:
- Linear:
linear - Standard:
ease,ease-in,ease-out,ease-in-out - Sine:
ease-in-sine,ease-out-sine,ease-in-out-sine - Quadratic:
ease-in-quad,ease-out-quad,ease-in-out-quad - Cubic:
ease-in-cubic,ease-out-cubic,ease-in-out-cubic - Quartic:
ease-in-quart,ease-out-quart,ease-in-out-quart - Quintic:
ease-in-quint,ease-out-quint,ease-in-out-quint - Exponential:
ease-in-expo,ease-out-expo,ease-in-out-expo - Circular:
ease-in-circ,ease-out-circ,ease-in-out-circ - Back:
ease-in-back,ease-out-back,ease-in-out-back - Elastic:
ease-in-elastic,ease-out-elastic,ease-in-out-elastic - Bounce:
ease-in-bounce,ease-out-bounce,ease-in-out-bounce - Custom:
cubic-bezier(x1,y1,x2,y2)
Animation Examples
{
"animations": [
{
"property": "opacity",
"from": 0,
"to": 1,
"startMs": 0,
"endMs": 1000,
"easing": "ease-in-out"
},
{
"property": "transform.scale",
"from": 0.5,
"to": 1.2,
"startMs": 500,
"endMs": 1500,
"easing": "ease-out-back"
},
{
"property": "config.color",
"from": "#ff0000",
"to": "#0000ff",
"startMs": 0,
"endMs": 2000,
"easing": "linear"
},
{
"property": "transform.rotation",
"from": 0,
"to": 360,
"startMs": 0,
"endMs": 2000,
"easing": "linear",
"loop": true,
"yoyo": false
}
]
}Keyframe Animations (NEW)
{
"keyframes": [
{
"property": "opacity",
"keyframes": [
{ "time": 0, "value": 0, "easing": "ease-in" },
{ "time": 500, "value": 1, "easing": "ease-out" },
{ "time": 1500, "value": 1, "easing": "ease-in" },
{ "time": 2000, "value": 0 }
]
}
]
}Scene Transitions (NEW)
{
"transitions": [
{
"fromScene": "scene1",
"toScene": "scene2",
"type": "crossfade",
"duration": 1000,
"easing": "ease-in-out"
},
{
"fromScene": "scene2",
"toScene": "scene3",
"type": "slide",
"duration": 800,
"easing": "ease-out",
"direction": "left"
},
{
"fromScene": "scene3",
"toScene": "scene4",
"type": "zoom",
"duration": 1200,
"easing": "ease-in-out",
"direction": "in"
}
]
}Audio System
Audio Track Configuration
interface AudioTrackSpec {
id: string; // Unique identifier
type: AudioTrackType; // Track type
src: string; // Audio file path/URL
startMs: number; // Start time in milliseconds
endMs?: number; // End time (optional)
volume?: number; // Volume 0-1 (default: 1)
fadeIn?: number; // Fade in duration (default: 0)
fadeOut?: number; // Fade out duration (default: 0)
loop?: boolean; // Loop track (default: false)
}
type AudioTrackType = 'voiceover' | 'ambience' | 'transition' | 'music' | 'sfx';Audio Example
{
"audio": [
{
"id": "background-music",
"type": "ambience",
"src": "audio/ambient.mp3",
"startMs": 0,
"volume": 0.6,
"fadeIn": 1000,
"loop": true
},
{
"id": "narrator",
"type": "voiceover",
"src": "audio/narration.mp3",
"startMs": 2000,
"volume": 1.0,
"fadeIn": 500,
"fadeOut": 500
}
]
}Performance Optimization
Quality Levels
The library automatically adapts performance based on device capabilities:
- Ultra: Maximum quality, all effects enabled
- High: High quality with some optimizations
- Medium: Balanced quality and performance
- Low: Optimized for performance, reduced effects
- Auto: Automatically adjusts based on device performance
Performance Guidelines
- Layer Count: Keep layers under 20 per scene for optimal performance
- Animation Complexity: Prefer transform and opacity animations over layout changes
- Asset Optimization: Use compressed images and audio files
- Canvas Particles: Limit particle count based on target devices
- Audio Tracks: Use compressed audio formats (MP3, AAC)
Device-Specific Optimizations
// The library automatically detects and optimizes for:
// - Device pixel ratio for sharp rendering
// - Available memory for asset caching
// - CPU capabilities for animation complexity
// - Network conditions for asset loading
// - Battery status for power-efficient renderingCLI Tools
Installation
The CLI is included with the package:
npx cinematic-cli --helpCommands
Validate Specification
# Basic validation
npx cinematic-cli validate --file spec.json
# Verbose output with details
npx cinematic-cli validate --file spec.json --verbose
# Save validation report
npx cinematic-cli validate --file spec.json --output report.jsonGenerate Preview
# Generate HTML preview
npx cinematic-cli preview --file spec.json
# Save to specific file
npx cinematic-cli preview --file spec.json --output preview.htmlTypeScript Support
Core Interfaces
import type {
CinematicRenderer2D,
CinematicSpec,
CinematicEvent,
CinematicScene,
LayerSpec,
AnimationTrackSpec,
AudioTrackSpec,
QualityLevel,
LayerType,
EasingType
} from 'cinematic-renderer2d';Custom Layer Development
import type { ICinematicLayer, LayerMountContext, FrameContext } from 'cinematic-renderer2d';
class CustomLayer implements ICinematicLayer {
id: string;
type: string;
zIndex: number;
constructor(config: any) {
this.id = config.id;
this.type = config.type;
this.zIndex = config.zIndex;
}
mount(ctx: LayerMountContext): void {
// Initialize layer
}
update(ctx: FrameContext): void {
// Update layer per frame
}
destroy(): void {
// Cleanup resources
}
}Examples
Complete Specification Example
{
"schemaVersion": "1.0.0",
"engine": {
"targetFps": 60,
"quality": "auto",
"debug": false
},
"events": [
{
"id": "intro",
"name": "Introduction Sequence",
"scenes": ["fade-in", "title-reveal", "fade-out"]
}
],
"scenes": [
{
"id": "fade-in",
"name": "Fade In",
"duration": 2000,
"layers": [
{
"id": "background",
"type": "gradient",
"zIndex": 1,
"config": {
"colors": ["#000000", "#1a1a1a"],
"direction": "to bottom"
},
"animations": [
{
"property": "opacity",
"from": 0,
"to": 1,
"startMs": 0,
"endMs": 2000,
"easing": "ease-in-out"
}
]
}
]
},
{
"id": "title-reveal",
"name": "Title Reveal",
"duration": 3000,
"layers": [
{
"id": "title",
"type": "textBlock",
"zIndex": 2,
"config": {
"text": "Welcome to CinematicRenderer2D",
"fontSize": "48px",
"color": "#ffffff",
"textAlign": "center"
},
"animations": [
{
"property": "transform.scale",
"from": 0.5,
"to": 1,
"startMs": 0,
"endMs": 1000,
"easing": "ease-out-back"
},
{
"property": "opacity",
"from": 0,
"to": 1,
"startMs": 0,
"endMs": 800,
"easing": "ease-out"
}
]
}
],
"audio": [
{
"id": "title-sound",
"type": "sfx",
"src": "audio/title-reveal.mp3",
"startMs": 500,
"volume": 0.8,
"fadeIn": 200
}
]
}
]
}Development
Project Structure
src/
├── core/ # Core engine and interfaces
│ ├── CinematicRenderer2D.ts
│ ├── LayerRegistry.ts
│ ├── Scheduler.ts
│ └── interfaces/
├── types/ # TypeScript definitions
│ ├── CinematicSpec.ts
│ ├── CompiledSpec.ts
│ └── AssetTypes.ts
├── parsing/ # JSON specification parsing
│ └── SpecParser.ts
├── animation/ # Animation system
│ └── AnimationCompiler.ts
├── rendering/ # Rendering backends
│ ├── RenderBackend.ts
│ ├── dom/
│ └── canvas2d/
├── assets/ # Asset management
│ └── AssetManager.ts
├── audio/ # Audio system
│ └── AudioSystem.ts
├── performance/ # Performance monitoring
│ └── QualitySystem.ts
├── debug/ # Debug tools
│ └── DebugOverlay.ts
├── cli/ # CLI tools
│ └── index.ts
└── adapters/ # Framework adapters
├── react/
└── angular/Available Scripts
npm run dev # Start development playground
npm run build # Build library for production
npm run build:check # Build and validate output
npm run test # Run test suite
npm run test:ui # Run tests with UI
npm run test:coverage # Run tests with coverage
npm run lint # Lint code
npm run lint:fix # Fix linting issues
npm run typecheck # Type checking
npm run preview # Preview built playground
npm run changeset # Create changeset for release
npm run version # Update version with changesets
npm run release # Publish to NPMTesting
The project uses comprehensive testing with:
- Unit Tests: Specific functionality testing
- Property-Based Tests: Universal behavior validation
- Integration Tests: End-to-end workflow testing
- Build Tests: Distribution package validation
# Run all tests
npm test
# Run specific test file
npm test -- src/core/Scheduler.test.ts
# Run tests in watch mode
npm test -- --watch
# Run with coverage
npm run test:coverageBrowser Support
- Modern Browsers: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
- Node.js: 16.0.0+ (for CLI tools)
- ES Modules: Full ESM support with CJS fallback
- TypeScript: 4.5+ for full type support
Performance Benchmarks
Typical performance on modern devices:
- Desktop: 120fps with 50+ layers
- Mobile: 60fps with 20+ layers
- Bundle Size: ~83KB minified + gzipped
- Memory Usage: <50MB for complex scenes
- Startup Time: <100ms initialization
Troubleshooting
Common Issues
Build Errors
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm installType Errors
# Ensure TypeScript is up to date
npm install typescript@latest --save-dev
npm run typecheckPerformance Issues
- Reduce layer count per scene
- Use 'low' or 'medium' quality settings
- Optimize asset file sizes
- Enable debug mode to monitor FPS
Debug Mode
Enable debug mode to monitor performance:
const renderer = new CinematicRenderer2D({
container: element,
spec: {
// ... your spec
engine: { debug: true }
}
});Debug overlay shows:
- Current FPS and frame time
- Active layers and their status
- Memory usage statistics
- Quality level and adaptations
Contributing
This project follows semantic versioning and uses changesets for release management.
Development Setup
git clone https://github.com/rvshekhar10/cinematicRenderer2D.git
cd cinematic-renderer2d
npm install
npm run devCreating Changes
# Make your changes
npm run changeset # Document your changes
npm run test # Ensure tests pass
npm run build # Verify build worksPublishing to NPM
See our publishing guides:
- 🚀 Quick Publish Guide - Fast 5-minute guide
- 📚 Complete Publishing Guide - Detailed instructions
- ✅ Publishing Checklist - Step-by-step checklist
License
MIT License - see LICENSE file for details.
Support
- 📖 Documentation: This README and TypeScript definitions
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
- 📧 Email: [email protected]
