dramaturgy
ساخت توالیهای موشن منسجم با ساختار صحنه، ریتم و زمانبندی هدفمند
این Skill انیمیشنهای پیچیده را به صحنهها و پردههای معنادار تقسیم میکند؛ از معرفی و توسعه تا تأکید و جمعبندی. با استفاده از الگوهای نمایشی و timelineهای GSAP، ترتیب حرکت عناصر و مدت هر بخش را مشخص میکند.
برای onboarding، transition صفحه، modal، داشبورد و hero animation مناسب است و ریتمهایی مثل measured، accelerating، staccato و legato را پیشنهاد میدهد. همچنین برای prefers-reduced-motion نسخهی سادهتر و دسترسپذیر ارائه میکند.
چه چیزی میگیرید
- ساختار صحنهای برای توالیهای کوتاه و چندمرحلهای
- انتخاب pacing profile و rhythm متناسب با هدف تجربه
- الگوهای هماهنگسازی عناصر مانند unison، canon، call-response و wave
- نمونههای قابلاستفاده با GSAP timeline
- راهکار کاهش حرکت برای کاربران دارای `prefers-reduced-motion`
برای چه کاری خوب است
- طراحی onboarding، wizard و جریانهای چندمرحلهای
- ساخت transition بین viewها یا نمایش تدریجی داشبورد
- هماهنگسازی چند عنصر در modal، hero section یا انیمیشن محصول
- زمانی که ریتم و روایت حرکت بهاندازهی خود انیمیشن اهمیت دارد
برای چه کاری نیست
- انیمیشنهای بسیار سادهی یک یا دو عنصر
- تنظیم جزئیات یک easing یا micro-interaction مستقل
- پروژههایی که به روایت صحنهای و هماهنگسازی چند حرکت نیاز ندارند
دربارهٔ این اسکیل
Dramaturgy
Theatrical composition for motion design. Structure animations into scenes and acts with intentional pacing, rhythm patterns, and ensemble choreography.
Standards Reference
| Standard | Documentation |
|---|---|
| W3C DTCG | designtokens.org |
| Theatrical Structure | Three-act structure |
| Material Design 3 | m3.material.io/styles/motion |
Quick Reference
Load from: tokens/dramaturgy.tokens.json
Scene Types
| Type | Duration | Intensity | Density | Purpose |
|---|---|---|---|---|
| establishing | 800ms | 0.4 | low | Orient user |
| development | 1200ms | 0.6 | medium | Build engagement |
| confrontation | 600ms | 0.8 | high | Demand action |
| resolution | 500ms | 0.5 | low | Confirm outcome |
| transition | 300ms | 0.3 | minimal | Bridge scenes |
Pacing Profiles
| Profile | Tempo | Use Case |
|---|---|---|
| measured | Consistent 400ms | Tutorials, data displays |
| accelerating | 500ms → 200ms | Countdowns, urgency |
| decelerating | 200ms → 600ms | Completion, settling |
| staccato | 100ms beat + 200ms pause | Alerts, emphasis |
| legato | 30% overlap | Smooth transitions |
| rubato | ±40% variation | Organic, playful |
Selection Guide
What's the experience structure?
├── Simple interaction (1-2 elements)
│ └── No dramaturgy needed
│ └── Use basic animation tokens
│
├── Component lifecycle (modal, card expand)
│ └── MICRO-ACT
│ └── setup → payoff (400ms total)
│
├── View transition
│ └── THREE-SCENE structure
│ └── establishing → action → resolution
│
├── Multi-step flow (wizard, onboarding)
│ └── THREE-ACT structure
│ └── Full dramatic composition
│
└── Complex orchestration (dashboard reveal, hero animation)
└── CUSTOM SCENES with rhythm patterns
Scene Composition
Establishing Scene
Set context before action.
// Modal establishing scene: scrim + container
const establishingScene = gsap.timeline();
// Set the stage
establishingScene.to('.scrim', {
opacity: 1,
duration: 0.3,
ease: 'power2.out'
});
// Container enters
establishingScene.fromTo('.modal',
{ opacity: 0, scale: 0.95 },
{
opacity: 1,
scale: 1,
duration: 0.5,
ease: 'power2.out'
},
'-=0.1' // Slight overlap
);
Development Scene
Build complexity and engagement.
// Content reveals in development scene
const developmentScene = gsap.timeline();
developmentScene.from('.modal-header', {
y: 20,
opacity: 0,
duration: 0.3,
ease: 'power2.out'
});
developmentScene.from('.modal-body', {
y: 20,
opacity: 0,
duration: 0.4,
ease: 'power2.out'
}, '-=0.15');
developmentScene.from('.modal-actions', {
y: 10,
opacity: 0,
duration: 0.3,
ease: 'power2.out'
}, '-=0.2');
Confrontation Scene
Demand user action.
// CTA emphasis in confrontation scene
const confrontationScene = gsap.timeline();
confrontationScene.to('.primary-cta', {
scale: 1.05,
boxShadow: '0 4px 20px rgba(33, 150, 243, 0.4)',
duration: 0.3,
ease: 'power2.out'
});
confrontationScene.to('.primary-cta', {
scale: 1,
duration: 0.3,
ease: 'elastic.out(1, 0.5)'
});
Resolution Scene
Confirm outcome, settle.
// Success resolution scene
const resolutionScene = gsap.timeline();
resolutionScene.to('.modal-content', {
opacity: 0,
y: -10,
duration: 0.2
});
resolutionScene.to('.success-state', {
opacity: 1,
scale: 1,
duration: 0.3,
ease: 'back.out(2)'
}, '-=0.1');
resolutionScene.from('.success-message', {
opacity: 0,
duration: 0.2
});
Pacing Profiles
Measured
Steady, predictable rhythm.
const measuredPacing = {
beatInterval: 400,
variation: 0.1, // ±10%
use: 'tutorials, step-by-step'
};
// Implementation
function measuredSequence(elements) {
gsap.from(elements, {
opacity: 0,
y: 20,
duration: 0.3,
stagger: 0.4, // Consistent 400ms
ease: 'power2.out'
});
}
Accelerating
Building momentum.
const acceleratingPacing = {
startInterval: 500,
endInterval: 200,
curve: 'ease-in'
};
// Implementation: countdown feel
function acceleratingSequence(elements) {
const count = elements.length;
elements.forEach((el, i) => {
// Interval decreases each step
const progress = i / (count - 1);
const interval = 500 - (300 * easeIn(progress));
gsap.from(el, {
opacity: 0,
scale: 0.9,
delay: i * interval / 1000,
duration: 0.2
});
});
}
function easeIn(t) {
return t * t;
}
Decelerating
Coming to rest.
const deceleratingPacing = {
startInterval: 200,
endInterval: 600,
curve: 'ease-out'
};
// Implementation: settling feel
function deceleratingSequence(elements) {
const count = elements.length;
elements.forEach((el, i) => {
const progress = i / (count - 1);
const interval = 200 + (400 * easeOut(progress));
gsap.from(el, {
opacity: 0,
y: 10,
delay: i * interval / 1000,
duration: 0.3,
ease: 'power2.out'
});
});
}
function easeOut(t) {
return 1 - Math.pow(1 - t, 2);
}
Staccato
Quick, punctuated beats.
const staccatoPacing = {
beatDuration: 100,
pauseDuration: 200
};
// Implementation: alert sequence
function staccatoSequence(element) {
const tl = gsap.timeline();
// Beat
tl.to(element, {
scale: 1.1,
duration: 0.1,
ease: 'power2.out'
});
// Pause (hold)
tl.to(element, {
scale: 1.1,
duration: 0.2
});
// Beat
tl.to(element, {
scale: 1,
duration: 0.1,
ease: 'power2.in'
});
return tl;
}
Legato
Smooth, connected flow.
const legatoPacing = {
overlap: 0.3 // 30% overlap
};
// Implementation
function legatoSequence(elements) {
const duration = 0.4;
const overlap = duration * 0.3;
const stagger = duration - overlap;
gsap.from(elements, {
opacity: 0,
x: 20,
duration: duration,
stagger: stagger,
ease: 'power2.inOut'
});
}
Rubato
Flexible, expressive timing.
const rubatoPacing = {
baseInterval: 350,
variation: 0.4 // ±40%
};
// Implementation: organic, playful feel
function rubatoSequence(elements) {
elements.forEach((el, i) => {
const baseDelay = i * 350;
const variation = (Math.random() - 0.5) * 2 * 0.4 * 350;
const delay = baseDelay + variation;
gsap.from(el, {
opacity: 0,
y: 10 + Math.random() * 10,
rotate: (Math.random() - 0.5) * 5,
delay: delay / 1000,
duration: 0.3,
ease: 'power2.out'
});
});
}
Rhythm Patterns
Apply musical timing to animation sequences.
Regular (4/4)
const regularRhythm = [1, 1, 1, 1]; // Equal beats
function applyRhythm(elements, baseDuration, pattern) {
const totalWeight = pattern.reduce((a, b) => a + b, 0);
elements.forEach((el, i) => {
const patternIndex = i % pattern.length;
const weight = pattern[patternIndex];
const duration = baseDuration * (weight / (totalWeight / pattern.length));
gsap.from(el, {
opacity: 0,
duration: duration / 1000
});
});
}
Waltz (3/4)
const waltzRhythm = [1.5, 0.75, 0.75]; // Strong-weak-weak
March
const marchRhythm = [1.2, 0.8, 1.2, 0.8]; // Strong-weak alternation
Ensemble Patterns
Coordinating multiple animated elements.
Unison
All elements move together.
gsap.from('.elements', {
y: 20,
opacity: 0,
duration: 0.3,
stagger: 0 // No stagger = unison
});
Canon
Same motion, staggered start.
gsap.from('.elements', {
y: 20,
opacity: 0,
duration: 0.3,
stagger: 0.1 // Canon
});
Call-Response
Leader, then followers.
const callResponse = gsap.timeline();
// Call (leader)
callResponse.from('.leader', {
scale: 0.8,
opacity: 0,
duration: 0.3
});
// Response (followers, delayed)
callResponse.from('.followers', {
scale: 0.9,
opacity: 0,
duration: 0.2,
stagger: 0.05
}, '+=0.15');
Wave
Flowing motion across elements.
gsap.from('.elements', {
y: 20,
opacity: 0,
duration: 0.4,
stagger: {
each: 0.04,
from: 'start', // or 'end', 'center', 'edges'
grid: 'auto'
}
});
Scene Templates
Modal Scene
const modalScene = {
structure: ['establishing', 'action', 'resolution'],
totalDuration: 600,
elements: {
establishing: ['.scrim', '.modal-container'],
action: ['.modal-header', '.modal-body', '.modal-footer'],
resolution: ['.focus-trap']
}
};
Page Transition Scene
const pageTransitionScene = {
structure: ['exit', 'transition', 'entrance'],
totalDuration: 500,
elements: {
exit: ['.current-page-content'],
transition: ['.page-container'],
entrance: ['.new-page-content']
}
};
Reduced Motion
For prefers-reduced-motion: reduce:
| Full Dramaturgy | Reduced |
|---|---|
| Multi-scene | Single fade |
| Pacing profiles | Instant |
| Ensemble patterns | Simultaneous |
| Rhythm variations | Uniform timing |
Cross-References
- See
narrative-arc/for story phases - See
sequencing/for stagger patterns - See
attention-choreography/for visual hierarchy - See
cinematic/for film techniques
References
references/scene-templates.md— Pre-built scene configurationsreferences/act-composition.md— Multi-scene act structures