hypnagaga_old/docs/GSAP_ANIMATIONS.md
2026-01-08 01:35:35 -05:00

201 lines
5.8 KiB
Markdown

# GSAP Animation System (Punch animations)
This project uses GSAP for scroll-driven punch animations (zoom in/out effects) via shortcodes. The system is intentionally minimal and focused on high-quality image reveals.
## Architecture Overview
The animation system is split into two main parts:
1. **Animations Library** ([`gsap-animations.js`](../src/assets/scripts/bundle/gsap-animations.js))
- Reusable zoom presets: `punchIn`, `punchOut`
- Default variables with simple override merging
- `shouldAnimate()` utility respecting `prefers-reduced-motion`
2. **Content Animations** ([`gsap-shortcode-init.js`](../src/assets/scripts/bundle/gsap-shortcode-init.js))
- Scroll-triggered animations in markdown/blog posts
- Paired shortcode reads JSON config and passes it through. The shortcode also passes arguments for a Tailwind class name.
- We must remember that this is the only function of Tailwind that we use and that we should consult files in ([`our design tokens`](../src/assets/css/global/global.css)), and be mindful of the fact that these animations will exist as containers of ([`prose.css`](../src/assets/css/global/blocks/prose.css)).
---
# For Content Authors
See [GSAP_USAGE.md](./GSAP_USAGE.md) for shortcode usage.
## Quick Start
### Punch In Animation
```markdown
{% gsapScrollAnim { "animationType": "punchIn", "focalX": 75, "focalY": 25, "startZoom": 1, "endZoom": 2.5 } %}
[{ "src": "/images/detail-photo.jpg", "alt": "Macro photography showing fine detail" }]
{% endgsapScrollAnim %}
```
---
# For Developers
## Configuration Options
All parameters are optional with sensible defaults and fully passed through:
```javascript
{
"animationType": "punchIn", // punchIn or punchOut
"scrollStart": "top 80%", // Timeline start
"scrollEnd": "bottom 20%", // Timeline end
"scrub": true, // Tie progress to scroll
"containerClass": "gsap-container",
"spillingInto": false, // false | true | 'prose' | 'bleed'
"pin": true,
"markers": false,
// Punch-specific overrides
"focalX": 50, // 0-100 (% from left)
"focalY": 50, // 0-100 (% from top)
"startZoom": 1, // 1 for punchIn, 2.5 for punchOut
"endZoom": 2.5, // 2.5 for punchIn, 1 for punchOut
"ease": "power2.inOut"
}
```
## Image Format
Images are defined as JSON array inside the paired shortcode:
```json
[{
"src": "/path/to/image.jpg",
"alt": "Required alt text",
"caption": "Optional caption text"
}, {
"src": "/path/to/image2.jpg",
"alt": "Second image",
"caption": "Another caption"
}]
```
Images are automatically optimized via Eleventy Image plugin (WebP/JPEG, responsive sizes).
## Example
### Zoom In to Focal Point
Draw attention to a specific detail in a high-resolution photograph:
```markdown
{% gsapScrollAnim {
"animationType": "zoomIn",
"focalX": 75,
"focalY": 25,
"startZoom": 1,
"endZoom": 2.5
} %}
[{
"src": "/images/detail-photo.jpg",
"alt": "Macro photography showing fine detail"
}]
{% endgsapScrollAnim %}
```
**Zoom Parameters:**
- `focalX` (0-100): Horizontal focal point percentage from left (default: 50)
- `focalY` (0-100): Vertical focal point percentage from top (default: 50)
- `startZoom`: Initial scale (default: 1 = 100%)
- `endZoom`: Final scale (default: 2.5 = 250%)
**zoomIn**: Starts with full image visible, zooms into the focal point
**zoomOut**: Starts zoomed into focal point, pulls back to show full image
High-resolution images (up to 3200px) are automatically loaded for zoom animations to preserve detail when scaled.
## ScrollTrigger Settings
### scrollStart / scrollEnd
Control when the animation begins and ends relative to viewport:
- `"top bottom"` - Element's top enters viewport bottom
- `"top 80%"` - Element's top at 80% viewport height
- `"center center"` - Element center aligns with viewport center
- `"bottom top"` - Element bottom exits viewport top
Default: `scrollStart: "top 80%"`, `scrollEnd: "bottom 20%"`
### scrub
When `true` (default), animation progress is tied directly to scroll position, enabling bidirectional playback.
When `false`, animation plays once when scroll position crosses `scrollStart` threshold.
## CSS Customization
Default wrapper class: `.gsap-container`
Generated structure:
```html
<div class="gsap-container" data-gsap-scroll-anim='{...}'>
<div class="gsap-item">
<figure class="gsap-image-wrapper">
<picture>
<img class="gsap-image" src="..." alt="...">
</picture>
<figcaption>...</figcaption>
</figure>
</div>
</div>
```
Add custom styles in your CSS:
```css
.gsap-container.featured-image {
max-width: 1200px;
margin: 0 auto;
}
.gsap-item {
margin-bottom: 2rem;
}
```
## Accessibility
- Respects `prefers-reduced-motion` - animations disabled automatically
- All images require `alt` text
- ScrollTrigger callbacks maintain proper ARIA states
## Turbo Drive Compatibility
Animations are automatically cleaned up and re-initialized on Turbo navigation:
- Contexts reverted before page change
- ScrollTrigger instances killed
- Re-initialized after new page loads
## Debugging
Enable debug markers to visualize scroll trigger points:
```markdown
{% gsapScrollAnim {
"animationType": "fadeIn",
"markers": true
} %}
[...]
{% endgsapScrollAnim %}
```
This shows colored markers in viewport indicating trigger start/end positions.
## Performance
- Animations use GPU-accelerated properties (`transform`, `opacity`)
- `will-change` applied for optimization
- ScrollTrigger efficiently batches calculations
- Contexts properly cleaned up on navigation
## Files
- Library: `src/assets/scripts/bundle/gsap-animations.js`
- Shortcode initializer: `src/assets/scripts/bundle/gsap-shortcode-init.js`
- Shortcode: `src/_config/shortcodes/gsap.js`
- CSS: `src/assets/css/global/utilities/gsap-animations.css`