use-scroll-animate 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,214 +1,217 @@
1
- <div align="center">
2
-
3
- # use-scroll-animate 🚀
4
-
5
- **A lightweight (~2.9KB gzipped), dependency-free scroll animation library for the modern web.**
6
-
7
- [![GitHub release (latest by date)](https://img.shields.io/github/v/release/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate/releases)
8
- [![GitHub repo size](https://img.shields.io/github/repo-size/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
11
-
12
- </div>
13
-
14
- ## Why `use-scroll-animate`?
15
-
16
- In 2025, performance is everything. Traditional scroll animation libraries often bundle heavy dependencies, rely on outdated scroll event listeners, or force you into a specific framework.
17
-
18
- `use-scroll-animate` is built differently:
19
- - ⚡ **Zero Dependencies**: Pure Vanilla JS/TypeScript.
20
- - 🚀 **High Performance**: Powered by `IntersectionObserver` and the native `Web Animations API`. No scroll event listeners, no layout thrashing.
21
- - 🪶 **Ultra Lightweight**: Only ~2.9KB gzipped.
22
- - 🧩 **Framework Agnostic**: Works seamlessly with Vanilla JS, React, Vue, Svelte, and more. First-class React Hooks and Vue Composables included.
23
- - ♿ **Accessible**: Respects `prefers-reduced-motion` out of the box.
24
-
25
- ## Installation
26
-
27
- ```bash
28
- npm install use-scroll-animate
29
- # or
30
- yarn add use-scroll-animate
31
- # or
32
- pnpm add use-scroll-animate
33
- ```
34
-
35
- ## Quick Start (Vanilla JS / HTML)
36
-
37
- The easiest way to use it is via HTML `data-sa` attributes.
38
-
39
- ```html
40
- <!-- 1. Add data-sa attributes to your elements -->
41
- <div data-sa data-sa-animation="fade-in-up" data-sa-duration="800">
42
- I will animate when scrolled into view!
43
- </div>
44
-
45
- <div data-sa data-sa-animation="zoom-in" data-sa-delay="200">
46
- Me too, with a delay!
47
- </div>
48
-
49
- <script type="module">
50
- // 2. Import and initialize
51
- import ScrollAnimate from 'use-scroll-animate';
52
-
53
- ScrollAnimate.init();
54
- </script>
55
- ```
56
-
57
- ## React Integration
58
-
59
- We provide a dedicated hook for React users.
60
-
61
- ```tsx
62
- import { createReactHooks } from 'use-scroll-animate/react';
63
- import React from 'react';
64
-
65
- const { useScrollAnimate, useScrollStagger } = createReactHooks(React);
66
-
67
- function App() {
68
- // Single element animation
69
- const titleRef = useScrollAnimate({ animation: 'fade-in-down', duration: 1000 });
70
-
71
- // Staggered list animation
72
- const listRef = useScrollStagger({ animation: 'fade-in-up', stagger: 100 });
73
-
74
- return (
75
- <main>
76
- <h1 ref={titleRef}>Welcome to my site</h1>
77
-
78
- <ul ref={listRef}>
79
- <li>Item 1</li>
80
- <li>Item 2</li>
81
- <li>Item 3</li>
82
- </ul>
83
- </main>
84
- );
85
- }
86
- ```
87
-
88
- ## Vue 3 Integration
89
-
90
- First-class support for Vue 3 Composition API.
91
-
92
- ```vue
93
- <template>
94
- <main>
95
- <h1 :ref="el => titleRef = el">Welcome to my site</h1>
96
- </main>
97
- </template>
98
-
99
- <script setup>
100
- import { ref, onMounted, onUnmounted } from 'vue';
101
- import { createVueComposables } from 'use-scroll-animate/vue';
102
-
103
- const { useScrollAnimate } = createVueComposables({ ref, onMounted, onUnmounted });
104
-
105
- const { animateRef: titleRef } = useScrollAnimate({
106
- animation: 'slide-right',
107
- duration: 800
108
- });
109
- </script>
110
- ```
111
-
112
- ## Built-in Animations
113
-
114
- Choose from 19 highly optimized built-in presets:
115
-
116
- - `fade-in`, `fade-in-up`, `fade-in-down`, `fade-in-left`, `fade-in-right`
117
- - `zoom-in`, `zoom-out`
118
- - `slide-up`, `slide-down`, `slide-left`, `slide-right`
119
- - `flip-x`, `flip-y`
120
- - `bounce`, `rotate-in`, `blur-in`
121
- - `skew-in`, `scale-x`, `scale-y`
122
-
123
- ## Configuration Options
124
-
125
- You can pass these options via JavaScript or as `data-sa-*` attributes in HTML.
126
-
127
- | Option | Type | Default | Description |
128
- |--------|------|---------|-------------|
129
- | `animation` | `string` \| `string[]` \| `object` | `['fade-in-up']` | Preset name, array of presets, or custom keyframes |
130
- | `duration` | `number` | `600` | Animation duration in ms |
131
- | `delay` | `number` | `0` | Delay before animation starts in ms |
132
- | `easing` | `string` | `ease` | CSS easing function (`linear`, `ease-out`, `spring`, etc.) |
133
- | `threshold` | `number` \| `number[]` | `0.1` | Intersection threshold (0 to 1) or array for progress |
134
- | `rootMargin` | `string` | `0px` | Root margin for IntersectionObserver |
135
- | `repeat` | `boolean` | `false` | Replay animation every time it enters viewport |
136
- | `stagger` | `number` | `0` | Delay between sibling elements in ms |
137
- | `parallax` | `object` | `{}` | Parallax effect configuration (x, y, rotate, scale, speed) |
138
- | `onProgress` | `(el, progress) => void` | `undefined` | Callback with scroll progress (0 to 1) |
139
-
140
- ## Advanced Usage
141
-
142
- ### Multiple Animations
143
-
144
- Combine multiple built-in presets for richer effects. For example, `['fade-in-up', 'zoom-in']`.
145
-
146
- ```html
147
- <div data-sa data-sa-animation="fade-in-up, zoom-in" data-sa-duration="1200">
148
- I will fade in from bottom and zoom in!
149
- </div>
150
- ```
151
-
152
- ### Parallax Effect
153
-
154
- Apply a parallax effect based on scroll position. Use `data-sa-parallax-x`, `data-sa-parallax-y`, `data-sa-parallax-rotate`, `data-sa-parallax-scale`.
155
-
156
- ```html
157
- <div data-sa data-sa-parallax-y="-100px" data-sa-parallax-speed="0.5">
158
- I will move up 100px as you scroll!
159
- </div>
160
-
161
- <div data-sa data-sa-parallax-rotate="30" data-sa-parallax-speed="0.8">
162
- I will rotate 30 degrees as you scroll!
163
- </div>
164
- ```
165
-
166
- ### Scroll Progress Listener
167
-
168
- Get real-time scroll progress (0 to 1) for an element.
169
-
170
- ```javascript
171
- import ScrollAnimate from 'use-scroll-animate';
172
-
173
- ScrollAnimate.observe('.progress-bar', {
174
- onProgress: (el, progress) => {
175
- (el as HTMLElement).style.width = `${progress * 100}%`;
176
- }
177
- });
178
- ```
179
-
180
- ### Custom Animations
181
-
182
- You can define your own animations using the Web Animations API keyframe format:
183
-
184
- ```javascript
185
- import ScrollAnimate from 'use-scroll-animate';
186
-
187
- ScrollAnimate.observe('.custom-box', {
188
- animation: {
189
- from: { opacity: 0, transform: 'scale(0.5) rotate(-45deg)' },
190
- to: { opacity: 1, transform: 'scale(1) rotate(0deg)' }
191
- },
192
- duration: 1000,
193
- easing: 'spring'
194
- });
195
- ```
196
-
197
- ### Callbacks
198
-
199
- ```javascript
200
- ScrollAnimate.observe('.track-me', {
201
- onStart: (el) => console.log('Animation started on', el),
202
- onComplete: (el) => console.log('Animation finished on', el),
203
- onEnter: (el) => console.log('Element entered viewport'),
204
- onLeave: (el) => console.log('Element left viewport')
205
- });
206
- ```
207
-
208
- ## Contributing
209
-
210
- Contributions are always welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
211
-
212
- ## License
213
-
214
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
1
+ <div align="center">
2
+
3
+ # use-scroll-animate 🚀
4
+
5
+ **A lightweight (~5KB gzipped), dependency-free scroll animation library for the modern web.**
6
+
7
+ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate/releases)
8
+ [![GitHub repo size](https://img.shields.io/github/repo-size/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
+
11
+ [English](./README.md) | [简体中文](./README_zh.md) | [日本語](./README_ja.md)
12
+
13
+ </div>
14
+
15
+ ## Why `use-scroll-animate`?
16
+
17
+ In 2025, performance is everything. Traditional scroll animation libraries often bundle heavy dependencies, rely on outdated scroll event listeners, or force you into a specific framework.
18
+
19
+ `use-scroll-animate` is built differently:
20
+ - ⚡ **Zero Dependencies**: Pure Vanilla JS/TypeScript.
21
+ - 🚀 **High Performance**: Powered by `IntersectionObserver` and the native `Web Animations API`. No scroll event listeners by default (the opt-in scroll-progress mode uses a single passive, rAF-throttled listener, only while tracked elements are on screen).
22
+ - 🪶 **Ultra Lightweight**: ~4.8KB gzipped for the core (tree-shaken, minified ESM); everything incl. `sequence`, `staggerChildren` and the React/Vue helpers is ~6.1KB (UMD ~6.2KB).
23
+ - 🧩 **Framework Agnostic**: Works seamlessly with Vanilla JS, React, Vue, Svelte, and more. First-class React Hooks and Vue Composables included.
24
+ - ♿ **Accessible**: Respects `prefers-reduced-motion` out of the box (content is shown immediately, no entrance or parallax motion).
25
+ - 🖥️ **SSR-safe**: Importing (and even calling) the API on the server is a no-op.
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install use-scroll-animate
31
+ ```
32
+
33
+ ## v1.4.0 New Features ✨
34
+
35
+ ### True scroll progress (`progressMode: 'scroll'`)
36
+ By default `onProgress` reports the element's *visible ratio*, which never reaches 1 for elements taller than the screen. Opt in to real scroll progress: `0` when the element's top reaches the bottom of the viewport, `1` when its bottom leaves the top.
37
+
38
+ ```js
39
+ ScrollAnimate.observe('.chapter', {
40
+ progressMode: 'scroll',
41
+ onProgress: (el, p) => el.style.setProperty('--progress', p),
42
+ });
43
+ ```
44
+
45
+ Parallax uses the same progress, so `progressMode: 'scroll'` also gives smooth parallax on tall sections. HTML: `data-sa-progress="scroll"`. Also exported as a helper: `getScrollProgress(el, root?)`.
46
+
47
+ ### Stagger dynamically added children
48
+ `staggerChildren()` (vanilla), `useScrollStagger()` (React **and now Vue**) accept `observeChildren: true`. A `MutationObserver` picks up children added later (infinite lists, "load more"): those added before the reveal join the stagger; those added after it animate when they scroll into view, staggered per batch.
49
+
50
+ ```js
51
+ import { staggerChildren } from 'use-scroll-animate';
52
+ const stop = staggerChildren(document.querySelector('#feed'), {
53
+ animation: 'fade-in-up', stagger: 60, observeChildren: true,
54
+ });
55
+ // later: stop();
56
+ ```
57
+
58
+ ### Timelines with `sequence()`
59
+ Chain animations across elements. Each step starts when the previous one ends; `gap` adds a pause (negative values overlap) and `at` sets an absolute start time.
60
+
61
+ ```js
62
+ import { sequence } from 'use-scroll-animate';
63
+
64
+ const tl = sequence([
65
+ { target: '.hero h1', animation: 'fade-in-up', duration: 700 },
66
+ { target: '.hero p', animation: 'blur-in', gap: -300 },
67
+ { target: '.hero .btn', animation: 'scale-up', stagger: 80 },
68
+ ], { trigger: '.hero', easing: 'soft-spring' }); // auto-plays once when .hero enters
69
+
70
+ await tl.play(); // or play manually; resolves when every step is done
71
+ tl.cancel(); // stop and leave everything visible
72
+ ```
73
+
74
+ ### New presets
75
+ `scale-up`, `blur-in-up`, `flip-up`, `flip-down`, `rotate-left`, `rotate-right`, and clip-path reveals `clip-up`, `clip-down`, `clip-left`, `clip-right`, `clip-circle`.
76
+
77
+ ### Smaller memory footprint
78
+ Finished `once` elements are dropped from the registry right after they animate (unless they still need parallax/`onProgress`), so long pages and SPAs don't keep thousands of records alive. They're remembered in a `WeakSet`, so `init()`/`observe()` never replay them. Set `createScrollAnimate({ autoUnregister: false })` to keep them listed in `getObservedElements()` as before.
79
+
80
+ ### Proper `exports` map
81
+ Node ESM (`import`) resolves to `dist/index.mjs`, CommonJS (`require`) to `dist/index.js`, each with matching bundled types. The legacy `main`/`module`/`unpkg` fields and `dist/*` deep imports keep working.
82
+
83
+ ## v1.3.0: Custom Easing 🎨
84
+
85
+ You can now use custom cubic-bezier curves or even JavaScript functions to create complex physical effects.
86
+
87
+ ### 1. Cubic-Bezier Array
88
+ Pass an array of 4 numbers to define a custom cubic-bezier curve.
89
+
90
+ ```javascript
91
+ ScrollAnimate.observe('.box', {
92
+ animation: 'fade-in-up',
93
+ easing: [0.68, -0.55, 0.265, 1.55] // Custom bounce effect
94
+ });
95
+ ```
96
+
97
+ ### 2. Custom Easing Function
98
+ Pass a function `(t: number) => number` for complete control over the animation timing.
99
+
100
+ ```javascript
101
+ ScrollAnimate.observe('.box', {
102
+ easing: (t) => t * t * (3 - 2 * t) // Custom smooth-step
103
+ });
104
+ ```
105
+
106
+ ### 3. New Physics Presets
107
+ We've added high-quality physics-based easing presets:
108
+ - `spring`: Standard spring effect.
109
+ - `soft-spring`: Gentle, bouncy entrance.
110
+ - `heavy-bounce`: Dramatic bounce effect.
111
+
112
+ ## Quick Start (Vanilla JS / HTML)
113
+
114
+ ```html
115
+ <div data-sa data-sa-animation="fade-in-up" data-sa-easing="soft-spring">
116
+ I have a soft spring effect!
117
+ </div>
118
+
119
+ <div data-sa data-sa-animation="zoom-in" data-sa-easing="[0.34, 1.56, 0.64, 1]">
120
+ I use a custom cubic-bezier array!
121
+ </div>
122
+
123
+ <script type="module">
124
+ import ScrollAnimate from 'use-scroll-animate';
125
+ ScrollAnimate.init();
126
+ </script>
127
+ ```
128
+
129
+ ## Options
130
+
131
+ | Option | Type | Default | Description |
132
+ |--------|------|---------|-------------|
133
+ | `animation` | `string` \| `string[]` \| `{ from, to }` | `'fade-in-up'` | Preset name, array of presets to combine, or custom keyframes |
134
+ | `duration` | `number` | `600` | Duration in ms |
135
+ | `delay` | `number` | `0` | Delay in ms |
136
+ | `easing` | `string` \| `number[]` \| `function` | `'ease'` | CSS easing, preset (`spring`, `soft-spring`, `heavy-bounce`), cubic-bezier array, or `(t) => number` |
137
+ | `threshold` | `number` \| `number[]` | `0.1` | IntersectionObserver threshold(s) |
138
+ | `rootMargin` | `string` | `'0px'` | IntersectionObserver root margin |
139
+ | `once` | `boolean` | `true` | Animate only the first time the element enters |
140
+ | `repeat` | `boolean` | `false` | Re-hide on leave and replay on every entry |
141
+ | `offset` | `number` | `0` | Trigger the animation this many px after the element enters the viewport |
142
+ | `stagger` | `number` | `0` | Extra delay (ms) per sibling revealed in the same batch |
143
+ | `parallax` | `{ x, y, rotate, scale, speed }` | `{}` | Scroll-driven parallax (keeps running after the entrance animation) |
144
+ | `onStart` / `onComplete` / `onEnter` / `onLeave` | `(el) => void` | – | Lifecycle callbacks |
145
+ | `onProgress` | `(el, progress) => void` | – | Progress (0–1) as the element scrolls — visible ratio, or true scroll progress with `progressMode: 'scroll'` |
146
+ | `progressMode` | `'ratio'` \| `'scroll'` | `'ratio'` | How `onProgress`/parallax progress is measured (`'scroll'`: 0 = top enters at the bottom, 1 = bottom leaves at the top) |
147
+
148
+ Every option is also available as a data attribute: `data-sa-animation`, `data-sa-duration`, `data-sa-delay`, `data-sa-easing`, `data-sa-threshold`, `data-sa-root-margin`, `data-sa-once`, `data-sa-repeat`, `data-sa-offset`, `data-sa-stagger`, `data-sa-progress`, `data-sa-parallax-x|y|rotate|scale|speed`.
149
+
150
+ **Presets:** `fade-in`, `fade-in-up|down|left|right`, `zoom-in`, `zoom-out`, `scale-up`, `flip-x`, `flip-y`, `flip-up`, `flip-down`, `slide-up|down|left|right`, `bounce`, `rotate-in`, `rotate-left`, `rotate-right`, `blur-in`, `blur-in-up`, `skew-in`, `scale-x`, `scale-y`, `clip-up|down|left|right`, `clip-circle`, `shimmer`, `pulse`, `swing`. Combine them with an array, e.g. `['fade-in', 'clip-up']`.
151
+
152
+ **Global config** (`createScrollAnimate(config)` / `configure()`): `defaultAnimation`, `defaultDuration`, `defaultDelay`, `defaultEasing`, `defaultThreshold`, `defaultRootMargin`, `defaultRepeat`, `defaultOnce`, `defaultOffset`, `hiddenClass`, `visibleClass`, `useClassNames`, `disabled`, `root`, `autoUnregister` (default `true`).
153
+
154
+ ## Instance API
155
+
156
+ ```js
157
+ import ScrollAnimate, { createScrollAnimate } from 'use-scroll-animate';
158
+
159
+ ScrollAnimate.init(root?); // observe every [data-sa] element (safe to call again after DOM changes)
160
+ ScrollAnimate.observe(target, opts); // selector, Element, NodeList or Element[]
161
+ ScrollAnimate.unobserve(target); // stop observing (elements that never animated are made visible)
162
+ ScrollAnimate.animate(target, opts); // play an animation right now
163
+ ScrollAnimate.refresh(); // rebuild observers, e.g. after configure({ root })
164
+ ScrollAnimate.configure({ ... }); // update global defaults
165
+ ScrollAnimate.destroy(); // disconnect everything
166
+
167
+ const sa = createScrollAnimate({ root: document.querySelector('#scroller') }); // isolated instance
168
+
169
+ // Helpers (tree-shakeable)
170
+ import { sequence, staggerChildren, getScrollProgress } from 'use-scroll-animate';
171
+ ```
172
+
173
+ Via a `<script>` tag (UMD build), the default instance lives at `ScrollAnimate.default`:
174
+
175
+ ```html
176
+ <script src="https://unpkg.com/use-scroll-animate"></script>
177
+ <script>ScrollAnimate.default.init();</script>
178
+ ```
179
+
180
+ ## React & Vue
181
+
182
+ ```jsx
183
+ import React from 'react';
184
+ import { createReactHooks } from 'use-scroll-animate';
185
+ const { useScrollAnimate, useScrollStagger } = createReactHooks(React);
186
+
187
+ function Card() {
188
+ const ref = useScrollAnimate({ animation: 'zoom-in', easing: 'spring' });
189
+ return <div ref={ref}>Hello</div>;
190
+ }
191
+ ```
192
+
193
+ ```js
194
+ import { ref, onMounted, onUnmounted } from 'vue';
195
+ import { createVueComposables } from 'use-scroll-animate';
196
+ const { useScrollAnimate, useScrollStagger } = createVueComposables({ ref, onMounted, onUnmounted });
197
+ const { animateRef } = useScrollAnimate({ animation: 'fade-in-left' });
198
+ const { staggerRef } = useScrollStagger({ stagger: 60, observeChildren: true }); // <ul ref="staggerRef">
199
+ ```
200
+
201
+ ```jsx
202
+ // React: also animate items appended later
203
+ function Feed({ items }) {
204
+ const ref = useScrollStagger({ animation: 'fade-in-up', stagger: 60, observeChildren: true });
205
+ return <ul ref={ref}>{items.map((i) => <li key={i.id}>{i.title}</li>)}</ul>;
206
+ }
207
+ ```
208
+
209
+ Hooks and composables share the core engine, so `once`, `offset`, custom easing functions, parallax and reduced-motion handling behave exactly like the vanilla API.
210
+
211
+ ## Contributing
212
+
213
+ Contributions are always welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.
214
+
215
+ ## License
216
+
217
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/README_ja.md CHANGED
@@ -1,69 +1,106 @@
1
- <div align="center">
2
-
3
- # use-scroll-animate 🚀
4
-
5
- **軽量(~2.9KB gzipped)、依存関係なしのモダンWeb向けスクロールアニメーションライブラリ。**
6
-
7
- [![GitHub release (latest by date)](https://img.shields.io/github/v/release/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate/releases)
8
- [![GitHub repo size](https://img.shields.io/github/repo-size/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
-
11
- [English](./README.md) | [简体中文](./README_zh.md)
12
-
13
- </div>
14
-
15
- ## なぜ `use-scroll-animate` なのか?
16
-
17
- 2025年、パフォーマンスはすべてです。従来のスクロールアニメーションライブラリは、重い依存関係をバンドルしたり、古いスクロールイベントリスナーに依存したり、特定のフレームワークを強制したりすることがよくあります。
18
-
19
- `use-scroll-animate` は違います:
20
- - ⚡ **依存関係なし**:純粋な Vanilla JS/TypeScript。
21
- - 🚀 **高パフォーマンス**:`IntersectionObserver` とネイティブの `Web Animations API` で駆動。スクロールイベントリスナーなし、レイアウトスラッシングなし。
22
- - 🪶 **超軽量**:Gzip後わずか約2.9KB。
23
- - 🧩 **フレームワークに依存しない**:Vanilla JS、React、Vue、Svelteなどとシームレスに動作。一流の React Hooks と Vue Composables を内蔵。
24
- - ♿ **アクセシブル**:`prefers-reduced-motion` を標準でサポート。
25
-
26
- ## インストール
27
-
28
- ```bash
29
- npm install use-scroll-animate
30
- ```
31
-
32
- ## クイックスタート (Vanilla JS / HTML)
33
-
34
- 最も簡単な方法は、HTML の `data-sa` 属性を使用することです。
35
-
36
- ```html
37
- <!-- 1. 要素に data-sa 属性を追加 -->
38
- <div data-sa data-sa-animation="fade-in-up" data-sa-duration="800">
39
- スクロールされるとアニメーションします!
40
- </div>
41
-
42
- <script type="module">
43
- // 2. インポートして初期化
44
- import ScrollAnimate from 'use-scroll-animate';
45
- ScrollAnimate.init();
46
- </script>
47
- ```
48
-
49
- ## v1.2.0 の新機能
50
-
51
- - **一度だけ実行 (Once)**:アニメーション実行後に監視を自動停止し、リソースを節約。
52
- - **オフセット (Offset)**:要素がビューポートに入ってから何ピクセル後にアニメーションを開始するかを指定可能。
53
- - **新しいプリセット**:`shimmer`(シマー)、`pulse`(パルス)、`swing`(スイング)を追加。
54
- - **多言語サポート**:中国語と日本語のドキュメントを追加。
55
-
56
- ## 主な設定
57
-
58
- | オプション | 型 | デフォルト | 説明 |
59
- |--------|------|---------|-------------|
60
- | `animation` | `string` \| `string[]` | `'fade-in-up'` | プリセット名またはプリセットの配列 |
61
- | `duration` | `number` | `600` | アニメーションの長さ (ms) |
62
- | `delay` | `number` | `0` | アニメーションの遅延 (ms) |
63
- | `once` | `boolean` | `true` | 一度だけ実行するかどうか |
64
- | `offset` | `number` | `0` | アニメーションを開始するビューポートのオフセット (px) |
65
- | `parallax` | `object` | `{}` | パララックス効果の設定 |
66
-
67
- ## ライセンス
68
-
69
- このプロジェクトは MIT ライセンスの下でライセンスされています - 詳細は [LICENSE](LICENSE) ファイルを参照してください。
1
+ <div align="center">
2
+
3
+ # use-scroll-animate 🚀
4
+
5
+ **軽量(~5KB gzipped)、依存関係なしのモダンWeb向けスクロールアニメーションライブラリ。**
6
+
7
+ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate/releases)
8
+ [![GitHub repo size](https://img.shields.io/github/repo-size/HarrisonCN/use-scroll-animate?style=flat-square)](https://github.com/HarrisonCN/use-scroll-animate)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
10
+
11
+ [English](./README.md) | [简体中文](./README_zh.md) | [日本語](./README_ja.md)
12
+
13
+ </div>
14
+
15
+ ## なぜ `use-scroll-animate` なのか?
16
+
17
+ 2025年、パフォーマンスはすべてです。従来のスクロールアニメーションライブラリは、重い依存関係をバンドルしたり、古いスクロールイベントリスナーに依存したり、特定のフレームワークを強制したりすることがよくあります。
18
+
19
+ `use-scroll-animate` は違います:
20
+ - ⚡ **依存関係なし**:純粋な Vanilla JS/TypeScript。
21
+ - 🚀 **高パフォーマンス**:`IntersectionObserver` とネイティブの `Web Animations API` で駆動。デフォルトではスクロールイベントリスナーなし(オプトインのスクロール進捗モードは、対象要素が画面内にある間だけ passive・rAF スロットルのリスナーを1つ使用)、レイアウトスラッシングなし。
22
+ - 🪶 **超軽量**:Gzip後コア約4.8KB(`sequence`・`staggerChildren`・React/Vue ヘルパーを含む全体で約6.1KB)。
23
+ - 🧩 **フレームワークに依存しない**:Vanilla JS、React、Vue、Svelteなどとシームレスに動作。一流の React Hooks と Vue Composables を内蔵。
24
+ - ♿ **アクセシブル**:`prefers-reduced-motion` を標準でサポート。
25
+
26
+ ## インストール
27
+
28
+ ```bash
29
+ npm install use-scroll-animate
30
+ ```
31
+
32
+ ## クイックスタート (Vanilla JS / HTML)
33
+
34
+ 最も簡単な方法は、HTML の `data-sa` 属性を使用することです。
35
+
36
+ ```html
37
+ <!-- 1. 要素に data-sa 属性を追加 -->
38
+ <div data-sa data-sa-animation="fade-in-up" data-sa-duration="800">
39
+ スクロールされるとアニメーションします!
40
+ </div>
41
+
42
+ <script type="module">
43
+ // 2. インポートして初期化
44
+ import ScrollAnimate from 'use-scroll-animate';
45
+ ScrollAnimate.init();
46
+ </script>
47
+ ```
48
+
49
+ ## v1.4.0 の新機能 ✨
50
+
51
+ - **本当のスクロール進捗 `progressMode: 'scroll'`**(オプトイン):`onProgress` はデフォルトで要素の表示比率を返すため、画面より高い要素では 1 に到達しません。有効にすると、要素の上端がビューポート下端に達したとき `0`、下端がビューポート上端を抜けたとき `1` になります。パララックスも同じ進捗を使用します。HTML では `data-sa-progress="scroll"`。ヘルパー `getScrollProgress(el, root?)` もエクスポートされています。
52
+
53
+ ```js
54
+ ScrollAnimate.observe('.chapter', {
55
+ progressMode: 'scroll',
56
+ onProgress: (el, p) => el.style.setProperty('--progress', p),
57
+ });
58
+ ```
59
+
60
+ - **動的に追加された子要素のスタッガー**:`staggerChildren()`(Vanilla)と `useScrollStagger()`(React、**Vue にも新たに対応**)に `observeChildren: true` を追加。`MutationObserver` で後から追加された子要素(無限リスト、「もっと見る」)を検出します。表示前に追加された要素はスタッガーに加わり、表示後に追加された要素はビューポートに入ったときにバッチ単位でスタッガー再生されます。
61
+
62
+ ```js
63
+ import { staggerChildren } from 'use-scroll-animate';
64
+ const stop = staggerChildren(document.querySelector('#feed'), { stagger: 60, observeChildren: true });
65
+ ```
66
+
67
+ - **タイムライン `sequence()`**:複数要素のアニメーションを連結。各ステップは前のステップの終了後に開始し、`gap` で間隔(負の値で重ね合わせ)、`at` で絶対開始時刻を指定できます。`trigger` を指定するとその要素が表示されたときに一度だけ自動再生します。
68
+
69
+ ```js
70
+ import { sequence } from 'use-scroll-animate';
71
+ const tl = sequence([
72
+ { target: '.hero h1', animation: 'fade-in-up', duration: 700 },
73
+ { target: '.hero p', animation: 'blur-in', gap: -300 },
74
+ { target: '.hero .btn', animation: 'scale-up', stagger: 80 },
75
+ ], { trigger: '.hero' });
76
+ await tl.play(); // すべて完了すると resolve。tl.cancel() で停止し要素は表示されたまま
77
+ ```
78
+
79
+ - **新しいプリセット**:`scale-up`、`blur-in-up`、`flip-up`、`flip-down`、`rotate-left`、`rotate-right`、clip-path による `clip-up`、`clip-down`、`clip-left`、`clip-right`、`clip-circle`。
80
+ - **メモリ使用量の削減**:`once` 要素はアニメーション開始後に自動でレジストリから削除されます(パララックス/`onProgress` が必要な要素を除く)。`WeakSet` で記憶されるため、`init()`/`observe()` で再生されることはありません。従来の挙動は `createScrollAnimate({ autoUnregister: false })`。
81
+ - **正しい `exports` マップ**:Node ESM は `dist/index.mjs`、CommonJS は `dist/index.js` に解決され、それぞれ対応する型定義付き。従来の `main`/`module`/`unpkg` と `dist/*` のディープインポートも引き続き利用可能。
82
+
83
+ ## v1.2.0 の新機能
84
+
85
+ - **一度だけ実行 (Once)**:アニメーション実行後に監視を自動停止し、リソースを節約。
86
+ - **オフセット (Offset)**:要素がビューポートに入ってから何ピクセル後にアニメーションを開始するかを指定可能。
87
+ - **新しいプリセット**:`shimmer`(シマー)、`pulse`(パルス)、`swing`(スイング)を追加。
88
+ - **多言語サポート**:中国語と日本語のドキュメントを追加。
89
+
90
+ ## 主な設定
91
+
92
+ | オプション | 型 | デフォルト | 説明 |
93
+ |--------|------|---------|-------------|
94
+ | `animation` | `string` \| `string[]` | `'fade-in-up'` | プリセット名またはプリセットの配列 |
95
+ | `duration` | `number` | `600` | アニメーションの長さ (ms) |
96
+ | `delay` | `number` | `0` | アニメーションの遅延 (ms) |
97
+ | `once` | `boolean` | `true` | 一度だけ実行するかどうか |
98
+ | `offset` | `number` | `0` | アニメーションを開始するビューポートのオフセット (px) |
99
+ | `parallax` | `object` | `{}` | パララックス効果の設定 |
100
+ | `stagger` | `number` | `0` | 同じバッチで表示される兄弟要素ごとの追加遅延 (ms) |
101
+ | `onProgress` | `(el, progress) => void` | – | スクロール進捗のコールバック (0–1) |
102
+ | `progressMode` | `'ratio'` \| `'scroll'` | `'ratio'` | 進捗の計算方法:表示比率または本当のスクロール進捗 |
103
+
104
+ ## ライセンス
105
+
106
+ このプロジェクトは MIT ライセンスの下でライセンスされています - 詳細は [LICENSE](LICENSE) ファイルを参照してください。