react-gsap-aos 1.0.2 → 1.1.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
@@ -2,9 +2,18 @@
2
2
 
3
3
  輕量的 GSAP + ScrollTrigger 整合,用法類似 AOS,專為 React / Next.js 設計。
4
4
 
5
- 動畫樣式參考: https://github.com/michalsnik/aos
5
+ 動畫樣式參考: [AOS](https://github.com/michalsnik/aos)
6
6
 
7
- ## 快速安裝
7
+ ## 功能
8
+
9
+ - 基於 GSAP + ScrollTrigger 的捲動觸發動畫
10
+ - API 模仿 AOS,易於 React / Next.js 使用
11
+ - 支援 data-aos 屬性與函式轉換
12
+ - 可在多個區塊平行使用,避免互相干擾
13
+ - TypeScript 完整支援,包含動畫/緩動/錨點型別
14
+ - 輕量且 SSR 友善,具備卸載清理機制
15
+
16
+ ## 安裝
8
17
 
9
18
  ```bash
10
19
  pnpm install react-gsap-aos gsap @gsap/react
@@ -23,108 +32,128 @@ pnpm install react-gsap-aos gsap @gsap/react
23
32
 
24
33
  ## 快速開始
25
34
 
26
- 1. Next.js / SSR 請在頂層加入 `"use client"`
27
- 2. 在需要動畫的頁面或元件中呼叫 `useAOSInitial`,並將回傳的 `containerRef` 綁定到最外層容器。
28
-
29
- > ⚠️ 不建議在 `app/layout.tsx` 綁定動畫,因為 GSAP 應在頁面卸載時正確清理;建議在每個頁面的區塊綁定。
30
-
31
- > `"overflow-hidden"` 樣式是解決動畫元素起始階段溢出問題。
32
-
33
35
  ```tsx
34
- "use client";
35
-
36
- import { useAOSInitial } from "react-gsap-aos";
36
+ import { AOSProvider } from "react-gsap-aos/client";
37
37
 
38
38
  export default function Demo() {
39
- const { containerRef } = useAOSInitial<HTMLDivElement>();
40
-
41
39
  return (
42
- <div ref={containerRef} className="overflow-hidden">
43
- {/* 動畫區塊 */}
44
- </div>
40
+ <AOSProvider className="overflow-hidden">
41
+ <div data-aos-container>
42
+ <div data-aos="fade-up" data-aos-offset="200">
43
+ Hello AOS
44
+ </div>
45
+ </div>
46
+ </AOSProvider>
45
47
  );
46
48
  }
47
49
  ```
48
50
 
49
- `useAOSInitial` 只會監聽並影響綁定元素下的所有標記為動畫的子元素,要注意的是不要嵌套使用 `useAOSInitial`:
51
+ ## 用法
50
52
 
51
- ```tsx
52
- function Demo() {
53
- const { containerRef } = useAOSInitial<HTMLDivElement>();
53
+ ### 設置 `AOSProvider`
54
54
 
55
- return (
56
- <div ref={containerRef} className="overflow-hidden">
57
- {/* ❌ 不要嵌套使用 useAOSInitial */}
58
- <Box />
59
- </div>
60
- );
61
- }
55
+ 只要把 `AOSProvider` 包覆在需要動畫的區塊外層,
56
+ 元件內的所有子元素就會自動被監聽與啟動動畫。
62
57
 
63
- function Box() {
64
- const { containerRef } = useAOSInitial<HTMLDivElement>();
58
+ > `"overflow-hidden"` 樣式是解決動畫元素起始階段溢出問題。
59
+
60
+ ```tsx
61
+ import { AOSProvider } from "react-gsap-aos/client";
65
62
 
63
+ export default function Demo() {
66
64
  return (
67
- <div ref={containerRef} className="overflow-hidden">
68
- {/* 動畫區塊 */}
69
- </div>
65
+ <AOSProvider className="overflow-hidden">{/* 動畫區塊 */}</AOSProvider>
70
66
  );
71
67
  }
72
68
  ```
73
69
 
74
- 如果有區塊需求可以並行使用:
70
+ > ⚠️ 不要巢狀使用 `AOSProvider`,會造成重複監聽與多餘動畫。
75
71
 
76
72
  ```tsx
77
- function Demo() {
73
+ import { AOSProvider } from "react-gsap-aos/client";
74
+
75
+ export default function Demo() {
78
76
  return (
79
- <div>
80
- {/* 並行使用互不影響 */}
81
- <Box />
82
- <Box2 />
83
- </div>
77
+ <AOSProvider>
78
+ {/* 會導致重複監聽元素以及創建動畫 */}
79
+ <AOSProvider />
80
+ </AOSProvider>
84
81
  );
85
82
  }
83
+ ```
86
84
 
87
- function Box() {
88
- const { containerRef } = useAOSInitial<HTMLDivElement>();
85
+ `AOSProvider` 是呼叫 `useAOSScope` hook 的包裝元件,大部分情況下使用此組件即可;
89
86
 
90
- return (
91
- <div ref={containerRef} className="overflow-hidden">
92
- {/* 動畫區塊 */}
93
- </div>
94
- );
95
- }
87
+ 如果你需要更細緻的控制,可以改用 [`useAOSScope`](#useaosscope)。
96
88
 
97
- function Box2() {
98
- const { containerRef } = useAOSInitial<HTMLDivElement>();
89
+ 此外該組件提供了兩個屬性供調整:
99
90
 
100
- return (
101
- <div ref={containerRef} className="overflow-hidden">
102
- {/* 動畫區塊 */}
103
- </div>
104
- );
105
- }
91
+ - `component`:渲染的容器元素,預設為 `'div'`。
92
+ - `options`:與 `toAOSProps` 同樣結構的默認動畫參數,會應用於該範圍內的所有新動畫元素。
93
+
94
+ ```tsx
95
+ <AOSProvider
96
+ component="section"
97
+ options={{
98
+ animation: "fade",
99
+ offset: 120,
100
+ delay: 0,
101
+ duration: 400,
102
+ easing: "none",
103
+ once: false,
104
+ mirror: false,
105
+ anchorPlacement: "top-bottom",
106
+ }}
107
+ ></AOSProvider>
106
108
  ```
107
109
 
108
- ## 區塊預設值
110
+ ### 使用 data attributes 設定動畫
109
111
 
110
- 若要在區塊層級覆蓋預設設定,可傳入選項:
112
+ 透過帶有 `data-aos-*` 開頭的屬性來調整行為
111
113
 
112
114
  ```tsx
113
- const { containerRef } = useAOSInitial<HTMLDivElement>({
114
- easing: "bounce",
115
- duration: 300,
116
- });
115
+ <div
116
+ data-aos="fade"
117
+ data-aos-offset={120}
118
+ data-aos-delay={0}
119
+ data-aos-duration={400}
120
+ data-aos-easing="none"
121
+ data-aos-mirror={false}
122
+ data-aos-once={false}
123
+ data-aos-anchor-placement="top-bottom"
124
+ >
125
+ Hello AOS
126
+ </div>
117
127
  ```
118
128
 
119
- > 此設定只會應用於該容器中新產生的動畫元素,不建議頻繁動態變更此項設定。
129
+ ### 使用 `toAOSProps` 設定動畫
130
+
131
+ 該函式提供完整型別且會過濾無效的屬性值後轉換成 data attributes
132
+
133
+ ```tsx
134
+ <div
135
+ {...toAOSProps({
136
+ animation: "fade",
137
+ offset: 120,
138
+ delay: 0,
139
+ duration: 400,
140
+ easing: "none",
141
+ once: false,
142
+ mirror: false,
143
+ anchorPlacement: "top-bottom",
144
+ })}
145
+ >
146
+ Hello AOS
147
+ </div>
148
+ ```
120
149
 
121
- ## 容器定位 data-aos-container
150
+ ### 容器定位 data-aos-container
122
151
 
123
- 為了避免 ScrollTrigger 計算偏移時造成觸發點不正確,請在需要的父容器上加上 `data-aos-container`:
152
+ 為了避免 ScrollTrigger 計算偏移時造成觸發點不正確,請在需要的父容器加上 `data-aos-container`:
124
153
 
125
154
  ```tsx
126
155
  return (
127
- <div ref={containerRef} className="overflow-hidden">
156
+ <AOSProvider className="overflow-hidden">
128
157
  {/* ✅ 指定定位容器 */}
129
158
  <div data-aos-container>
130
159
  <div data-aos="fade-up" data-aos-offset="200">
@@ -136,7 +165,7 @@ return (
136
165
  <div data-aos="fade-up" data-aos-offset="200">
137
166
  Hello AOS
138
167
  </div>
139
- </div>
168
+ </AOSProvider>
140
169
  );
141
170
  ```
142
171
 
@@ -157,51 +186,85 @@ return (
157
186
  </div>
158
187
  ```
159
188
 
160
- ## 使用`data-aos`屬性
189
+ ## API
190
+
191
+ ### `useAOSScope`
192
+
193
+ 這個 hook 是整個套件的核心,負責監聽子元素 `data-aos-*` 屬性來創建、修改動畫並且會在離開頁面時卸載動畫,`AOSProvider` 是它的輕量包裝元件,通常你只需使用 `AOSProvider`。
161
194
 
162
- 直接在元素上使用 `data-aos` 與相關屬性。
195
+ 若你想在函式元件中直接掌握 container ref,就可以直接使用此 hook。
196
+
197
+ 1. Next.js / SSR 專案在使用此 hook 的檔案最上方加上 `"use client"`。
198
+ 2. 呼叫後把回傳的 `containerRef` 綁定到最外層容器。
199
+
200
+ > ⚠️ 建議綁定在頁面或元件的區塊層級,不要放在 `app/layout.tsx`,以便 GSAP 在組件卸載時能正確清理。
163
201
 
164
202
  ```tsx
165
- <div
166
- data-aos="fade"
167
- data-aos-offset={120}
168
- data-aos-delay={0}
169
- data-aos-duration={400}
170
- data-aos-easing="none"
171
- data-aos-mirror={false}
172
- data-aos-once={false}
173
- data-aos-anchor-placement="top-bottom"
174
- >
175
- Hello AOS
176
- </div>
203
+ "use client";
204
+
205
+ import { useAOSScope } from "react-gsap-aos/client";
206
+
207
+ export default function Demo() {
208
+ const { containerRef } = useAOSScope<HTMLDivElement>();
209
+
210
+ return (
211
+ <div ref={containerRef} className="overflow-hidden">
212
+ {/* 動畫區塊 */}
213
+ </div>
214
+ );
215
+ }
177
216
  ```
178
217
 
179
- ## 使用 `toAOSProps` 函式
218
+ 不要巢狀呼叫 `useAOSScope`,但是你可以像下面這樣平行使用。
219
+
220
+ ```tsx
221
+ function Demo() {
222
+ return (
223
+ <div>
224
+ {/* ✅ 平行使用互不干涉 */}
225
+ <Box />
226
+ <Box2 />
227
+ </div>
228
+ );
229
+ }
230
+
231
+ function Box() {
232
+ const { containerRef } = useAOSScope<HTMLDivElement>();
233
+ return (
234
+ <div ref={containerRef} className="overflow-hidden">
235
+
236
+ </div>
237
+ );
238
+ }
239
+
240
+ function Box2() {
241
+ const { containerRef } = useAOSScope<HTMLDivElement>();
242
+ return (
243
+ <div ref={containerRef} className="overflow-hidden">
244
+
245
+ </div>
246
+ );
247
+ }
248
+ ```
180
249
 
181
- 取得經過型別檢查與過濾的屬性物件。
250
+ 若要在區塊層級覆蓋預設設定,可傳入選項:
182
251
 
183
252
  ```tsx
184
- <div
185
- {...toAOSProps({
186
- animation: "fade",
187
- offset: 120,
188
- delay: 0,
189
- duration: 400,
190
- easing: "none",
191
- once: false,
192
- mirror: false,
193
- anchorPlacement: "top-bottom",
194
- })}
195
- >
196
- Hello AOS
197
- </div>
253
+ const { containerRef } = useAOSScope<HTMLDivElement>({
254
+ easing: "bounce",
255
+ duration: 300,
256
+ });
198
257
  ```
199
258
 
259
+ > 此設定只會應用於該容器中新產生的動畫元素,不建議頻繁動態變更此項設定。
260
+
200
261
  ## 刷新動畫位置
201
262
 
202
263
  若動態修改 DOM(插入/移除元素或修改佈局),請手動呼叫:
203
264
 
204
265
  ```ts
266
+ "use client";
267
+
205
268
  import { refreshAOS } from "react-gsap-aos";
206
269
 
207
270
  refreshAOS();
@@ -213,17 +276,17 @@ refreshAOS();
213
276
 
214
277
  ### 動態 DOM 範例
215
278
 
216
- 以下範例示範在動態新增列表項目時,如何呼叫 `refreshAOS()` :
279
+ 以下範例示範在動態增減元素導致佈局變動時,如何呼叫 `refreshAOS()` :
217
280
 
218
281
  ```tsx
219
282
  "use client";
220
283
 
221
284
  import { useState, useEffect } from "react";
222
- import { useAOSInitial, refreshAOS } from "react-gsap-aos";
285
+ import { useAOSScope, refreshAOS } from "react-gsap-aos";
223
286
 
224
287
  export default function DynamicList() {
225
- const { containerRef } = useAOSInitial<HTMLDivElement>();
226
- const [show, setShow] = useState(boolean);
288
+ const { containerRef } = useAOSScope<HTMLDivElement>();
289
+ const [show, setShow] = useState(false);
227
290
 
228
291
  useEffect(() => {
229
292
  // 當 show 變動時,刷新 ScrollTrigger
@@ -331,7 +394,7 @@ export default function DynamicList() {
331
394
  - sine
332
395
  - sine.in
333
396
  - sine.out
334
- - sine.inOu
397
+ - sine.inOut
335
398
 
336
399
  ## AnchorPlacement
337
400
 
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+ import React__default, { ElementType, ComponentPropsWithoutRef } from 'react';
3
+ import { A as AOSAttributeOptions } from './toAOSProps-DBQmkOnG.mjs';
4
+ import { b as AnimationOptions } from './types-BXrsuTv7.mjs';
5
+
6
+ type AOSProviderProps<T extends ElementType> = {
7
+ component?: T;
8
+ options?: AOSAttributeOptions;
9
+ children?: React__default.ReactNode;
10
+ } & Omit<ComponentPropsWithoutRef<T>, "ref">;
11
+ declare function AOSProvider<T extends ElementType = "div">({ component, options, children, ...props }: AOSProviderProps<T>): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
12
+
13
+ /**
14
+ * 綁定 AOS 動畫範圍
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ "use client";
19
+
20
+ import {useAOSScope} from '@/aos';
21
+
22
+ export default function Demo() {
23
+ const {containerRef} = useAOSScope<HTMLDivElement>()
24
+ return (
25
+ <div ref={containerRef} className="overflow-hidden">
26
+ <div data-aos-container>
27
+ <div data-aos="fade-up">Hello AOS</div>
28
+ </div>
29
+ </div>
30
+ )
31
+ }
32
+ * ```
33
+ */
34
+ declare function useAOSScope<E extends HTMLElement = HTMLElement>(options?: Partial<AnimationOptions>): {
35
+ containerRef: React.RefObject<E | null>;
36
+ };
37
+
38
+ export { AOSProvider, useAOSScope };
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+ import React__default, { ElementType, ComponentPropsWithoutRef } from 'react';
3
+ import { A as AOSAttributeOptions } from './toAOSProps-Dx7ebLJd.js';
4
+ import { b as AnimationOptions } from './types-BXrsuTv7.js';
5
+
6
+ type AOSProviderProps<T extends ElementType> = {
7
+ component?: T;
8
+ options?: AOSAttributeOptions;
9
+ children?: React__default.ReactNode;
10
+ } & Omit<ComponentPropsWithoutRef<T>, "ref">;
11
+ declare function AOSProvider<T extends ElementType = "div">({ component, options, children, ...props }: AOSProviderProps<T>): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
12
+
13
+ /**
14
+ * 綁定 AOS 動畫範圍
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ "use client";
19
+
20
+ import {useAOSScope} from '@/aos';
21
+
22
+ export default function Demo() {
23
+ const {containerRef} = useAOSScope<HTMLDivElement>()
24
+ return (
25
+ <div ref={containerRef} className="overflow-hidden">
26
+ <div data-aos-container>
27
+ <div data-aos="fade-up">Hello AOS</div>
28
+ </div>
29
+ </div>
30
+ )
31
+ }
32
+ * ```
33
+ */
34
+ declare function useAOSScope<E extends HTMLElement = HTMLElement>(options?: Partial<AnimationOptions>): {
35
+ containerRef: React.RefObject<E | null>;
36
+ };
37
+
38
+ export { AOSProvider, useAOSScope };