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

5.8 KiB

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)
  • Reusable zoom presets: punchIn, punchOut
  • Default variables with simple override merging
  • shouldAnimate() utility respecting prefers-reduced-motion
  1. Content Animations (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), and be mindful of the fact that these animations will exist as containers of (prose.css).

For Content Authors

See GSAP_USAGE.md for shortcode usage.

Quick Start

Punch In Animation

{% 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:

{
  "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:

[{
  "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:

{% 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:

<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:

.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:

{% 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