Render Hooks
Lightweight customization through hooks that extend the default rendering pipeline
Render hooks provide a lightweight way to customize waveform rendering by injecting custom logic at specific points during the default rendering pipeline. Unlike custom renderers, hooks extend the built-in rendering behavior rather than replacing it entirely.
Understanding Render Hooks
Section titled “Understanding Render Hooks”Render hooks allow you to “hook into” the rendering process at predefined points:
beforeRender
– Called before any rendering begins- Default background rendering – Library renders the background waveform
afterBackground
– Called after background is rendered- Default progress rendering – Library renders progress overlay (if progress > 0)
afterProgress
– Called after progress is rendered- Default progress line rendering – Library renders progress line
afterComplete
– Called when all rendering is complete
Interface Definition
Section titled “Interface Definition”interface RenderHook { beforeRender?: ( ctx: CanvasRenderingContext2D, cache: RenderCache, options: Required<WaveformOptions> ) => void;
afterBackground?: ( ctx: CanvasRenderingContext2D, cache: RenderCache, options: Required<WaveformOptions> ) => void;
afterProgress?: ( ctx: CanvasRenderingContext2D, cache: RenderCache, options: Required<WaveformOptions>, progress: number ) => void;
afterComplete?: ( ctx: CanvasRenderingContext2D, cache: RenderCache, options: Required<WaveformOptions> ) => void;}
Basic Usage
Section titled “Basic Usage”Simple Overlay Example
Section titled “Simple Overlay Example”import { WaveformRenderer } from "waveform-renderer";
const waveform = new WaveformRenderer(canvas, peaks);
waveform.setRenderHooks({ afterComplete: (ctx, cache, options) => { ctx.fillStyle = "rgba(0, 0, 0, 0.3)"; ctx.font = "12px Arial"; ctx.fillText("Audio Player", 10, 20); },});
Progress Indicator
Section titled “Progress Indicator”waveform.setRenderHooks({ afterProgress: (ctx, cache, options, progress) => { const x = cache.canvasWidth * progress;
ctx.fillStyle = "#ff0000"; ctx.beginPath(); ctx.arc(x, cache.canvasHeight / 2, 4, 0, Math.PI * 2); ctx.fill(); },});
Hook Management
Section titled “Hook Management”Setting Hooks
Section titled “Setting Hooks”waveform.setRenderHooks({ afterComplete: (ctx, cache, options) => { // Custom rendering logic },});
Clearing Hooks
Section titled “Clearing Hooks”waveform.clearRenderHooks();
Conditional Hooks
Section titled “Conditional Hooks”waveform.setRenderHooks({ afterProgress: (ctx, cache, options, progress) => { if (progress > 0.1) { this.drawProgressIndicator(ctx, cache, progress); } },
afterComplete: (ctx, cache, options) => { if (options.position === "center") { this.drawCenterAlignedOverlay(ctx, cache); } else { this.drawStandardOverlay(ctx, cache); } },});
Hooks vs Custom Renderers
Section titled “Hooks vs Custom Renderers”Aspect | Render Hooks | Custom Renderers |
---|---|---|
Purpose | Extend default rendering | Replace default rendering |
Complexity | Lightweight, targeted changes | Complete rendering control |
Default Behavior | Preserves library’s rendering | Overrides library’s rendering |
Use Cases | Overlays, effects, annotations | Complete visual redesign |
Performance | Minimal impact | Can optimize or impact performance |
Maintenance | Library handles core updates | Must maintain all rendering logic |
When to Use Render Hooks
Section titled “When to Use Render Hooks”Recommended for:
- Overlays or annotations
- Custom progress indicators
- Visual effects on top of the waveform
- Debug visualizations
- Watermarks or branding
- Beat markers or time indicators
- Real-time frequency overlays
Avoid when:
- Completely changing visualization style
- Implementing new rendering algorithms
- Creating entirely different visual representations
Best Practices
Section titled “Best Practices”Canvas State Management
Section titled “Canvas State Management”Always save and restore canvas state:
afterBackground: (ctx, cache, options) => { ctx.save();
try { ctx.fillStyle = "red"; ctx.fillRect(0, 0, 100, 100); } finally { ctx.restore(); }};
Performance Considerations
Section titled “Performance Considerations”Keep hooks lightweight:
// ✅ EfficientafterProgress: (ctx, cache, options, progress) => { const x = cache.canvasWidth * progress; ctx.fillRect(x - 1, 0, 2, cache.canvasHeight);};
// ❌ Avoid heavy workafterProgress: (ctx, cache, options, progress) => { for (let i = 0; i < 10000; i++) { // Expensive operations }};
Error Handling
Section titled “Error Handling”Wrap hook logic in try-catch:
afterComplete: (ctx, cache, options) => { try { this.complexRenderingOperation(ctx, cache); } catch (error) { console.warn("Hook rendering failed:", error); }};
Available Parameters
Section titled “Available Parameters”All hook functions receive:
ctx
– Canvas rendering contextcache
– Pre-computed rendering data (bar positions, dimensions)options
– Full waveform configurationprogress
– Current progress value (only inafterProgress
)
Next Steps
Section titled “Next Steps”- Explore Custom Renderers for full rendering control
- Check API Reference for parameter documentation
- Try the Interactive Demo to experiment with hooks