Hot To Use
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
📚 Scroll Trigger - Complete Usage Guide
Everything you need to create stunning scroll animations in your Angular application.
🚀 Installation
1. Import the Directive
import { EnhancedScrollTriggerDirective } from '@widgets-editor/scroll-trigger';
@Component({
selector: 'app-my-component',
standalone: true,
imports: [EnhancedScrollTriggerDirective],
template: `...`
})
export class MyComponent {}
🎯 Basic Usage
Example 1: Simple Fade-In
<div enhancedScrollTrigger="fade-section"
[animationPreset]="'fade-in'">
<h2>This fades in when scrolled into view!</h2>
</div>
Example 2: Custom Trigger Positions
<div enhancedScrollTrigger="hero-title"
[animationPreset]="'slide-up'"
[start]="'top 80%'"
[end]="'top 20%'">
<h1>Animated Hero Title</h1>
</div>
Example 3: With Visual Triggers
<div enhancedScrollTrigger="product-card"
[animationPreset]="'explode'"
[showTriggers]="true"
[triggerColor]="'#22c55e'">
<div class="product">Product Card</div>
</div>
🎨 Animation Presets
Available Presets
| Preset | Effect | Best For |
|---|---|---|
fade-in |
Gradual opacity increase | Subtle reveals |
slide-up |
Upward motion + fade | Text content |
slide-down |
Downward motion + fade | Headers |
slide-left |
Left motion + fade | Side content |
slide-right |
Right motion + fade | Side content |
scale-in |
Grow from center | Images, cards |
scale-out |
Shrink to center | Dismissals |
explode |
Dramatic expansion | Hero sections |
vortex |
Spinning rotation | Eye-catching reveals |
morph |
Shape transformation | Creative effects |
magnetize |
Pull-in effect | Interactive elements |
spiral |
Spiral rotation | Decorative elements |
Usage
// Simple preset
<div [animationPreset]="'fade-in'"></div>
// With speed control
<div [animationPreset]="'explode'"
[animationSpeed]="'fast'"></div>
// With delay
<div [animationPreset]="'vortex'"
[animationDelay]="500"></div>
🎯 Trigger Position Syntax
Keyword Positions
// Element position keywords: 'top' | 'center' | 'bottom'
// Viewport position keywords: 'top' | 'center' | 'bottom'
[start]="'top bottom'" // Element top hits viewport bottom
[start]="'center center'" // Element center aligns with viewport center
[start]="'bottom top'" // Element bottom reaches viewport top
Percentage Offsets
// Progress percentage for end trigger
[start]="'top bottom'"
[end]="'80%'" // Animation completes at 80% of distance
// Viewport percentage for start trigger
[start]="'top 20%'" // Trigger when element hits 20% from top
[end]="'bottom 80%'" // End when element bottom hits 80%
Pixel Offsets
[start]="'100px bottom'" // 100px offset from calculated position
[end]="'200px'" // 200px offset
Combined Syntax
// Element keyword + Viewport percentage
[start]="'top 25%'"
[end]="'bottom 75%'"
// With pixel offset
[start]="'center 50%'"
[end]="'100px'"
✏️ Visual Editor
Enable Visual Triggers
<div enhancedScrollTrigger="my-element"
[showTriggers]="true"
[triggerColor]="'#3b82f6'">
Content
</div>
Enable Edit Mode
<div enhancedScrollTrigger="my-element"
[showTriggers]="true"
[editMode]="true"
[triggerColor]="'#22c55e'">
Click me to open the editor!
Drag the trigger lines to adjust timing!
</div>
Global Control Example
@Component({
template: `
<button (click)="showTriggers.set(!showTriggers())">
{{ showTriggers() ? 'Hide' : 'Show' }} Triggers
</button>
<button (click)="editMode.set(!editMode())">
{{ editMode() ? 'Exit' : 'Enter' }} Edit Mode
</button>
<div enhancedScrollTrigger="elem-1"
[showTriggers]="showTriggers()"
[editMode]="editMode()"
[triggerColor]="'#22c55e'">
Element 1
</div>
`
})
export class MyComponent {
protected showTriggers = signal(false);
protected editMode = signal(false);
}
🎬 Multi-Step Animations
Configuration Structure
import { ScrollAnimationConfig } from '@widgets-editor/scroll-trigger';
const config: ScrollAnimationConfig = {
id: 'complex-card',
animationPreset: 'fade-in',
startTrigger: 'top bottom',
endTrigger: '90%',
exitBehavior: 'none',
scrubbing: false,
pinning: false,
steps: [
{
id: 'step-1',
animationPreset: 'fade-in',
delay: 0,
duration: 300,
easing: 'ease-out',
parallel: false
},
{
id: 'step-2',
animationPreset: 'slide-up',
delay: 100,
duration: 400,
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
parallel: true // Runs WITH step-1
},
{
id: 'step-3',
animationPreset: 'scale-in',
delay: 0,
duration: 500,
easing: 'ease-in-out',
parallel: false // Runs AFTER step-2
}
]
};
Visual Editor UI
- Click element to open editor
- Navigate to "Multi-Step" tab
- Click "➕ Add Keyframe"
- Configure each step:
- Animation preset
- Delay (ms)
- Duration (ms)
- Easing function
- Parallel execution
- Save - automatically persists!
💾 Automatic Persistence
Using Flash Persistence
import { autoFlashState } from '@flash-persistence';
@Component({
template: `
@for (element of elements(); track element.id) {
<div [enhancedScrollTrigger]="element.id"
[animationPreset]="element.animation"
[start]="element.start"
[end]="element.end">
{{ element.label }}
</div>
}
`
})
export class MyComponent {
// ✨ Automatically persists across page refreshes!
protected elements = autoFlashState('my-scroll-elements', [
{
id: 'hero-1',
label: 'Hero Section',
animation: 'fade-in' as FlashAnimationPreset,
start: 'top bottom',
end: '80%'
}
]);
// Update any element - automatically saved!
updateElement(id: string, config: Partial<ElementConfig>) {
this.elements.update(els =>
els.map(el => el.id === id ? { ...el, ...config } : el)
);
// No manual save() needed! ✨
}
}
🎮 Complete API Reference
Directive Inputs
| Input | Type | Default | Description |
|---|---|---|---|
enhancedScrollTrigger |
string |
required | Unique element ID |
start |
string |
'top bottom' |
When animation starts |
end |
string |
'80%' |
When animation completes |
animationPreset |
FlashAnimationPreset |
undefined |
Animation type |
animationSpeed |
'instant' | 'fast' | 'elegant' | 'smooth' | 'slow' |
'elegant' |
Animation speed |
animationDelay |
number |
0 |
Delay before animation (ms) |
scrub |
boolean | number |
false |
Smooth scrubbing |
pin |
boolean |
false |
Pin element during animation |
showTriggers |
boolean |
false |
Show visual trigger guides |
triggerColor |
string |
undefined |
Custom trigger color |
editMode |
boolean |
false |
Enable draggable triggers |
debug |
boolean |
false |
Enable verbose logging |
Directive Outputs
| Output | Type | Description |
|---|---|---|
onEnter |
EventEmitter<ScrollTriggerEvent> |
Fires when entering trigger zone |
onLeave |
EventEmitter<ScrollTriggerEvent> |
Fires when leaving trigger zone |
onUpdate |
EventEmitter<ScrollTriggerEvent> |
Fires on scroll (if scrubbing enabled) |
onToggle |
EventEmitter<ScrollTriggerEvent> |
Fires on enter/leave toggle |
Event Data Structure
interface ScrollTriggerEvent {
direction: 'forward' | 'reverse';
progress: number; // 0-1
velocity: number; // Scroll speed
isActive: boolean; // Currently in trigger zone?
}
📋 Common Recipes
Recipe 1: Staggered List Animations
@Component({
template: `
@for (item of items; track item.id; let i = $index) {
<div [enhancedScrollTrigger]="'item-' + i"
[animationPreset]="'slide-up'"
[animationDelay]="i * 100"
[start]="'top 90%'"
[end]="'top 60%'">
{{ item.title }}
</div>
}
`
})
Recipe 2: Scroll-Linked Progress Bar
@Component({
template: `
<div enhancedScrollTrigger="progress-section"
[start]="'top bottom'"
[end]="'bottom top'"
[scrub]="true"
(onUpdate)="updateProgress($event)">
<div class="progress-bar" [style.width.%]="progress()"></div>
</div>
`
})
export class MyComponent {
protected progress = signal(0);
updateProgress(event: ScrollTriggerEvent) {
this.progress.set(event.progress * 100);
}
}
Recipe 3: Pinned Section with Animation
<div enhancedScrollTrigger="pinned-hero"
[animationPreset]="'scale-in'"
[pin]="true"
[start]="'top top'"
[end]="'+=500'">
<h1>This stays pinned while animating!</h1>
</div>
Recipe 4: Conditional Animations
<div [enhancedScrollTrigger]="'conditional-elem'"
[animationPreset]="isDesktop() ? 'explode' : 'fade-in'"
[start]="isDesktop() ? 'top 80%' : 'top 90%'">
Different animations for different devices!
</div>
🎯 Performance Tips
1. Use Unique IDs
// ✅ Good
enhancedScrollTrigger="hero-section-title"
enhancedScrollTrigger="product-card-3"
// ❌ Bad
enhancedScrollTrigger="div"
enhancedScrollTrigger="element"
2. Disable Triggers in Production
<div [enhancedScrollTrigger]="'my-elem'"
[showTriggers]="isDevMode()"
[editMode]="false">
3. Use Simple Trigger Positions
// ✅ Fast calculation
[start]="'top bottom'"
[end]="'80%'"
// ⚠️ Slower (but still fast)
[start]="'center 37.5%'"
[end]="'bottom 87.23%'"
4. Group Similar Animations
// Instead of 10 individual configs, use one shared config
const sharedConfig = {
start: 'top bottom',
end: '80%',
animation: 'fade-in'
};
🐛 Troubleshooting
Issue: Animations not triggering
Solution: Ensure element has content/height and is scrollable into view.
// ❌ Problem: No height
<div enhancedScrollTrigger="empty"></div>
// ✅ Solution: Has content
<div enhancedScrollTrigger="with-content">
<h2>Content Here</h2>
</div>
Issue: Triggers not visible
Solution: Check showTriggers and triggerColor inputs.
// Make sure these are set
[showTriggers]="true"
[triggerColor]="'#22c55e'" // Any valid CSS color
Issue: Persistence not working
Solution: Ensure Flash Persistence is configured in main.ts:
import { provideAutoFlashPersistence } from '@flash-persistence';
bootstrapApplication(AppComponent, {
providers: [
provideAutoFlashPersistence({
namespace: 'my-app'
})
]
});
🚀 Next Steps
- System Overview - Architecture details
- Feature Roadmap - Upcoming features
- Progress Tracker - Implementation status
Ready to build? Start scrolling! 🎢