zz-shopify-components 0.0.27 → 0.0.28-beta.10

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +21 -21
  2. package/README.md +70 -56
  3. package/assets/ScrollTrigger.min.js +11 -11
  4. package/assets/gsap.min.js +11 -11
  5. package/assets/jquery.js +2 -2
  6. package/assets/lazy-video.js +2 -2
  7. package/assets/lazyload.min.js +1 -1
  8. package/assets/lozad.js +10 -10
  9. package/assets/site-jump.js +52 -52
  10. package/assets/site-jumpV2.js +35 -35
  11. package/assets/swiper-bundle.min.css +12 -12
  12. package/assets/swiper-bundle.min.js +13 -13
  13. package/assets/swiper.css +330 -330
  14. package/assets/zz-components.css +322 -322
  15. package/assets/zz-components.js +166 -166
  16. package/assets/zz-fade-in-content.js +169 -169
  17. package/assets/zz-http-request.js +73 -73
  18. package/assets/zz-world-video-comments-dialog.js +240 -240
  19. package/assets/zz-world-video-dialog.js +190 -190
  20. package/assets/zz-world-video-list.js +317 -317
  21. package/assets/zz-world-video.js +270 -270
  22. package/blocks/zz-accessories-item.liquid +188 -188
  23. package/blocks/zz-accessories-swiper.liquid +223 -223
  24. package/blocks/zz-button.liquid +216 -216
  25. package/blocks/zz-content-description-html.liquid +201 -201
  26. package/blocks/zz-content-description.liquid +209 -209
  27. package/blocks/zz-flex-layout-bg-block.liquid +524 -524
  28. package/blocks/zz-flex-layout-block.liquid +549 -549
  29. package/blocks/zz-flex-layout-widget.liquid +321 -321
  30. package/blocks/zz-full-screen-swiper.liquid +443 -443
  31. package/blocks/zz-icon.liquid +46 -46
  32. package/blocks/zz-mail.liquid +135 -135
  33. package/blocks/zz-mb-swiper-pc-flex.liquid +273 -273
  34. package/blocks/zz-price-tag-mini.liquid +106 -106
  35. package/blocks/zz-price-tag.liquid +41 -41
  36. package/blocks/zz-ratio-image.liquid +181 -181
  37. package/blocks/zz-ratio-video.liquid +115 -115
  38. package/blocks/zz-responsive-width-image.liquid +222 -222
  39. package/blocks/zz-responsive-width-video.liquid +166 -166
  40. package/blocks/zz-scroll-animate-bg-text.liquid +268 -268
  41. package/blocks/zz-scroll-cover.liquid +67 -67
  42. package/blocks/zz-tag.liquid +50 -50
  43. package/blocks/zz-text.liquid +227 -227
  44. package/blocks/zz-title.liquid +287 -287
  45. package/blocks/zz-video-button.liquid +84 -84
  46. package/blocks/zz-video-img-item.liquid +203 -203
  47. package/blocks/zz-video-img-list.liquid +166 -166
  48. package/blocks/zz-video-swiper-perview-item.liquid +221 -221
  49. package/blocks/zz-video-swiper-perview.liquid +585 -585
  50. package/blocks/zz-world-video.liquid +639 -639
  51. package/component.config.json +7 -7
  52. package/package.json +1 -1
  53. package/scripts/postinstall-v1.js +39 -39
  54. package/scripts/postinstall-v2.js +47 -47
  55. package/scripts/postinstall-v3.js +51 -51
  56. package/scripts/publish-npm.js +43 -43
  57. package/sections/zz-flex-layout-section.liquid +269 -269
  58. package/sections/zz-navigation-tab-v3.liquid +409 -409
  59. package/sections/zz-navigation-tab.liquid +411 -411
  60. package/sections/zz-shopping-card-list.liquid +399 -399
  61. package/sections/zz-video-collapse-swiper.liquid +522 -522
  62. package/sections/zz-video-tab-swiper.liquid +748 -748
  63. package/snippets/zz-button.liquid +70 -70
  64. package/snippets/zz-content-h3.liquid +15 -15
  65. package/snippets/zz-content-text.liquid +56 -56
  66. package/snippets/zz-h2.liquid +31 -31
  67. package/snippets/zz-h3.liquid +31 -31
  68. package/snippets/zz-h4.liquid +30 -30
  69. package/snippets/zz-h5.liquid +39 -39
  70. package/snippets/zz-h6.liquid +39 -39
  71. package/snippets/zz-icon-next.liquid +17 -17
  72. package/snippets/zz-icon-prev.liquid +17 -17
  73. package/snippets/zz-icon.liquid +74 -74
  74. package/snippets/zz-img-md.liquid +44 -44
  75. package/snippets/zz-img.liquid +44 -44
  76. package/snippets/zz-prev-next-blur-icon.liquid +36 -36
  77. package/snippets/zz-prev-next-btn.liquid +62 -62
  78. package/snippets/zz-price-tag.liquid +22 -22
  79. package/snippets/zz-spoke.liquid +142 -142
  80. package/snippets/zz-tag.liquid +22 -22
  81. package/snippets/zz-video-button.liquid +54 -54
  82. package/snippets/zz-video-md.liquid +117 -117
  83. package/snippets/zz-video.liquid +117 -117
@@ -1,166 +1,166 @@
1
- class ZZRadioTabsItem extends HTMLElement {
2
- constructor() {
3
- super();
4
- }
5
-
6
- connectedCallback() {
7
- // 创建radio input
8
- const groupName =
9
- this.closest('zz-radio-tabs')?.getAttribute('name') || 'option';
10
- const type =
11
- this.closest('zz-radio-tabs')?.getAttribute('type') || 'default';
12
- const value = this.getAttribute('value') || '';
13
- const slot = this.innerHTML;
14
- this.innerHTML = `
15
- <label class="zz-radio-tabs-wrapper">
16
- <input type="radio" name=${groupName} value=${value}>
17
- <div class="zz-radio-tabs-label">
18
- ${slot}
19
- </div>
20
- </label>
21
- `;
22
- }
23
- }
24
-
25
- /**
26
- * type: default, black 两种风格模式
27
- */
28
- class ZZRadioTabs extends HTMLElement {
29
- constructor() {
30
- super();
31
- }
32
- connectedCallback() {
33
- // 获取组件的type属性
34
- const type = this.getAttribute('type') || 'default';
35
- // 给自己加class
36
- this.classList.add('zz-radio-tabs');
37
- this.classList.add(`zz-radio-tabs-${type}`);
38
- }
39
-
40
- get value() {
41
- const selectedRadio = this.querySelector('input[type="radio"]:checked');
42
- return selectedRadio?.value;
43
- }
44
-
45
- set value(val) {
46
- const radio = this.querySelector(`input[type="radio"][value="${val}"]`);
47
- if (radio) {
48
- radio.checked = true;
49
- }
50
- }
51
- }
52
-
53
- // 注册自定义元素
54
- customElements.define('zz-radio-tabs-item', ZZRadioTabsItem);
55
- customElements.define('zz-radio-tabs', ZZRadioTabs);
56
-
57
- // 页面加载完成后执行
58
- document.addEventListener('DOMContentLoaded', function () {
59
- // 点击视频播放/暂停
60
- // 在 video 标签上添加 class='click-video-play-pause' 即可
61
- (function () {
62
- const videoPlayAndPause = document.querySelectorAll(
63
- '.click-video-play-pause'
64
- );
65
- videoPlayAndPause.forEach((video) => {
66
- video.classList.remove('video-play-pause');
67
- video.addEventListener('click', function () {
68
- if (this.paused) {
69
- this.play();
70
- } else {
71
- this.pause();
72
- }
73
- });
74
- });
75
- })();
76
- });
77
- /**
78
- * 视频按钮+弹窗
79
- */
80
- class ZZVideoBtn extends HTMLElement {
81
- constructor() {
82
- super();
83
- this.togglePopup = this.togglePopup.bind(this);
84
- this.popup = null;
85
- }
86
-
87
- connectedCallback() {
88
- this.querySelectorAll('.togglePopup').forEach((el) => {
89
- el.addEventListener('click', (event) => {
90
- console.log('click');
91
- if (event.target.tagName !== 'VIDEO') {
92
- this.togglePopup();
93
- }
94
- });
95
- });
96
- this.popup = this.querySelector('.popup');
97
-
98
- if (this.popup) {
99
- // 将 popup 移动到 body
100
- document.body.appendChild(this.popup);
101
- } else {
102
- console.error('Popup element not found.');
103
- }
104
- }
105
-
106
- disconnectedCallback() {
107
- if (this.popup && document.body.contains(this.popup)) {
108
- document.body.removeChild(this.popup); // 清理 popup 元素
109
- }
110
- }
111
-
112
- togglePopup() {
113
- if (!this.popup) return;
114
-
115
- const isHidden = this.popup.classList.contains('!tw-hidden');
116
-
117
- if (isHidden) {
118
- this.showPopup();
119
- } else {
120
- this.hidePopup();
121
- }
122
- }
123
-
124
- showPopup() {
125
- if (!this.popup) return;
126
-
127
- this.popup.classList.remove('!tw-hidden');
128
- gsap.fromTo(
129
- this.popup,
130
- { opacity: 0 },
131
- {
132
- opacity: 1,
133
- duration: 0.3,
134
- ease: 'linear',
135
- backdropFilter: 'blur(30px)',
136
- onComplete: () => {
137
- const video = this.popup.querySelector('video');
138
- if (video) {
139
- video.play();
140
- }
141
- },
142
- }
143
- );
144
- }
145
-
146
- hidePopup() {
147
- if (!this.popup) return;
148
-
149
- gsap.to(this.popup, {
150
- opacity: 0,
151
- duration: 0.3,
152
- ease: 'linear',
153
- onComplete: () => {
154
- this.popup.classList.add('!tw-hidden');
155
- const video = this.popup.querySelector('video');
156
- if (video) {
157
- video.pause();
158
- }
159
- },
160
- });
161
- }
162
- }
163
-
164
- if (!customElements.get('zz-video-button')) {
165
- customElements.define('zz-video-button', ZZVideoBtn);
166
- }
1
+ class ZZRadioTabsItem extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ }
5
+
6
+ connectedCallback() {
7
+ // 创建radio input
8
+ const groupName =
9
+ this.closest('zz-radio-tabs')?.getAttribute('name') || 'option';
10
+ const type =
11
+ this.closest('zz-radio-tabs')?.getAttribute('type') || 'default';
12
+ const value = this.getAttribute('value') || '';
13
+ const slot = this.innerHTML;
14
+ this.innerHTML = `
15
+ <label class="zz-radio-tabs-wrapper">
16
+ <input type="radio" name=${groupName} value=${value}>
17
+ <div class="zz-radio-tabs-label">
18
+ ${slot}
19
+ </div>
20
+ </label>
21
+ `;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * type: default, black 两种风格模式
27
+ */
28
+ class ZZRadioTabs extends HTMLElement {
29
+ constructor() {
30
+ super();
31
+ }
32
+ connectedCallback() {
33
+ // 获取组件的type属性
34
+ const type = this.getAttribute('type') || 'default';
35
+ // 给自己加class
36
+ this.classList.add('zz-radio-tabs');
37
+ this.classList.add(`zz-radio-tabs-${type}`);
38
+ }
39
+
40
+ get value() {
41
+ const selectedRadio = this.querySelector('input[type="radio"]:checked');
42
+ return selectedRadio?.value;
43
+ }
44
+
45
+ set value(val) {
46
+ const radio = this.querySelector(`input[type="radio"][value="${val}"]`);
47
+ if (radio) {
48
+ radio.checked = true;
49
+ }
50
+ }
51
+ }
52
+
53
+ // 注册自定义元素
54
+ customElements.define('zz-radio-tabs-item', ZZRadioTabsItem);
55
+ customElements.define('zz-radio-tabs', ZZRadioTabs);
56
+
57
+ // 页面加载完成后执行
58
+ document.addEventListener('DOMContentLoaded', function () {
59
+ // 点击视频播放/暂停
60
+ // 在 video 标签上添加 class='click-video-play-pause' 即可
61
+ (function () {
62
+ const videoPlayAndPause = document.querySelectorAll(
63
+ '.click-video-play-pause'
64
+ );
65
+ videoPlayAndPause.forEach((video) => {
66
+ video.classList.remove('video-play-pause');
67
+ video.addEventListener('click', function () {
68
+ if (this.paused) {
69
+ this.play();
70
+ } else {
71
+ this.pause();
72
+ }
73
+ });
74
+ });
75
+ })();
76
+ });
77
+ /**
78
+ * 视频按钮+弹窗
79
+ */
80
+ class ZZVideoBtn extends HTMLElement {
81
+ constructor() {
82
+ super();
83
+ this.togglePopup = this.togglePopup.bind(this);
84
+ this.popup = null;
85
+ }
86
+
87
+ connectedCallback() {
88
+ this.querySelectorAll('.togglePopup').forEach((el) => {
89
+ el.addEventListener('click', (event) => {
90
+ console.log('click');
91
+ if (event.target.tagName !== 'VIDEO') {
92
+ this.togglePopup();
93
+ }
94
+ });
95
+ });
96
+ this.popup = this.querySelector('.popup');
97
+
98
+ if (this.popup) {
99
+ // 将 popup 移动到 body
100
+ document.body.appendChild(this.popup);
101
+ } else {
102
+ console.error('Popup element not found.');
103
+ }
104
+ }
105
+
106
+ disconnectedCallback() {
107
+ if (this.popup && document.body.contains(this.popup)) {
108
+ document.body.removeChild(this.popup); // 清理 popup 元素
109
+ }
110
+ }
111
+
112
+ togglePopup() {
113
+ if (!this.popup) return;
114
+
115
+ const isHidden = this.popup.classList.contains('!tw-hidden');
116
+
117
+ if (isHidden) {
118
+ this.showPopup();
119
+ } else {
120
+ this.hidePopup();
121
+ }
122
+ }
123
+
124
+ showPopup() {
125
+ if (!this.popup) return;
126
+
127
+ this.popup.classList.remove('!tw-hidden');
128
+ gsap.fromTo(
129
+ this.popup,
130
+ { opacity: 0 },
131
+ {
132
+ opacity: 1,
133
+ duration: 0.3,
134
+ ease: 'linear',
135
+ backdropFilter: 'blur(30px)',
136
+ onComplete: () => {
137
+ const video = this.popup.querySelector('video');
138
+ if (video) {
139
+ video.play();
140
+ }
141
+ },
142
+ }
143
+ );
144
+ }
145
+
146
+ hidePopup() {
147
+ if (!this.popup) return;
148
+
149
+ gsap.to(this.popup, {
150
+ opacity: 0,
151
+ duration: 0.3,
152
+ ease: 'linear',
153
+ onComplete: () => {
154
+ this.popup.classList.add('!tw-hidden');
155
+ const video = this.popup.querySelector('video');
156
+ if (video) {
157
+ video.pause();
158
+ }
159
+ },
160
+ });
161
+ }
162
+ }
163
+
164
+ if (!customElements.get('zz-video-button')) {
165
+ customElements.define('zz-video-button', ZZVideoBtn);
166
+ }
@@ -1,169 +1,169 @@
1
- document.addEventListener('DOMContentLoaded', () => {
2
- gsap.registerPlugin(ScrollTrigger);
3
-
4
- // 从下往上显示
5
- (function () {
6
- const fadeDom = document.querySelectorAll('.fade-in-content');
7
- fadeDom.forEach((item) => {
8
- gsap.from(item, {
9
- scrollTrigger: {
10
- trigger: item,
11
- start: 'top 80%',
12
- toggleActions: 'play none none reverse',
13
- once: false, // 动画只播放一次
14
- },
15
- opacity: 0,
16
- y: 80,
17
- duration: 0.4,
18
- ease: 'power2.out',
19
- });
20
- });
21
- })();
22
-
23
- // 从左往右显示
24
- (function () {
25
- const fadeDom = document.querySelectorAll('.fade-in-from-left-content');
26
- fadeDom.forEach((item) => {
27
- gsap.from(item, {
28
- scrollTrigger: {
29
- trigger: item,
30
- start: 'top 80%',
31
- toggleActions: 'play none none reverse',
32
- once: false, // 动画只播放一次
33
- },
34
- opacity: 0,
35
- x: -80,
36
- duration: 0.4,
37
- ease: 'power1.out',
38
- });
39
- });
40
- })();
41
-
42
- // 从右往左显示
43
- (function () {
44
- const fadeDom = document.querySelectorAll('.fade-in-from-right-content');
45
- fadeDom.forEach((item) => {
46
- gsap.from(item, {
47
- scrollTrigger: {
48
- trigger: item,
49
- start: 'top 80%',
50
- toggleActions: 'play none none reverse',
51
- once: false, // 动画只播放一次
52
- },
53
- opacity: 0,
54
- x: 80,
55
- duration: 0.4,
56
- ease: 'power1.out',
57
- });
58
- });
59
- })();
60
-
61
- // 跟随滚动缓慢显示
62
- (function () {
63
- const fadeDom = document.querySelectorAll('.slow-reveal-content');
64
- fadeDom.forEach((item) => {
65
- gsap.from(item, {
66
- scrollTrigger: {
67
- trigger: item,
68
- start: 'top 80%',
69
- end: 'top 60%',
70
- toggleActions: 'play none none reverse',
71
- scrub: 1, // 平滑跟随滚动
72
- },
73
- opacity: 1,
74
- y: 100,
75
- duration: 0.4,
76
- ease: 'power1.out',
77
- });
78
- });
79
- })();
80
-
81
- // 按序从下显示(group)
82
- const el = document.querySelectorAll('.fade-in-box');
83
- el.forEach((item) => {
84
- // 过滤出不包含 no-fade-in 类名的子元素
85
- const children = Array.from(item.children).filter(
86
- (child) => !child.classList.contains('no-fade-in')
87
- );
88
- gsap.from(children, {
89
- scrollTrigger: {
90
- trigger: item,
91
- start: 'top 80%',
92
- toggleActions: 'play none none reverse',
93
- once: false, // 动画只播放一次
94
- },
95
- opacity: 0,
96
- y: 80,
97
- duration: 0.4,
98
- stagger: 0.2,
99
- ease: 'power2.out',
100
- });
101
- });
102
-
103
- // 按序从左进入显示
104
- const fromLeft = document.querySelectorAll('.fade-in-from-left');
105
- fromLeft.forEach((item) => {
106
- // 过滤出不包含 no-fade-in 类名的子元素
107
- const children = Array.from(item.children).filter(
108
- (child) => !child.classList.contains('no-fade-in')
109
- );
110
- gsap.from(children, {
111
- scrollTrigger: {
112
- trigger: item,
113
- start: 'top 80%',
114
- toggleActions: 'play none none reverse',
115
- once: false, // 动画只播放一次
116
- },
117
- opacity: 0,
118
- x: -80,
119
- duration: 0.4,
120
- stagger: 0.1,
121
- ease: 'power1.out',
122
- });
123
- });
124
-
125
- // 按序从右进入显示
126
- const fromRight = document.querySelectorAll('.fade-in-from-right');
127
- fromRight.forEach((item) => {
128
- // 过滤出不包含 no-fade-in 类名的子元素
129
- const children = Array.from(item.children).filter(
130
- (child) => !child.classList.contains('no-fade-in')
131
- );
132
- gsap.from(children, {
133
- scrollTrigger: {
134
- trigger: item,
135
- start: 'top 80%',
136
- toggleActions: 'play none none reverse',
137
- once: false,
138
- },
139
- opacity: 0,
140
- x: 80,
141
- duration: 0.4,
142
- stagger: 0.1,
143
- ease: 'power1.out',
144
- });
145
- });
146
- });
147
-
148
- // 跟随滚动缓慢显示
149
- const slowReveal = document.querySelectorAll('.slow-reveal');
150
- slowReveal.forEach((element) => {
151
- // 过滤出不包含 no-fade-in 类名的子元素
152
- const children = Array.from(element.children).filter(
153
- (child) => !child.classList.contains('no-fade-in')
154
- );
155
- gsap.from(children, {
156
- scrollTrigger: {
157
- trigger: element,
158
- start: 'top 80%',
159
- end: 'top 60%',
160
- scrub: 1, // 平滑跟随滚动
161
- toggleActions: 'play none none reverse',
162
- },
163
- opacity: 1,
164
- y: 100,
165
- duration: 0.4,
166
- stagger: 0.1,
167
- ease: 'power1.out',
168
- });
169
- });
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ gsap.registerPlugin(ScrollTrigger);
3
+
4
+ // 从下往上显示
5
+ (function () {
6
+ const fadeDom = document.querySelectorAll('.fade-in-content');
7
+ fadeDom.forEach((item) => {
8
+ gsap.from(item, {
9
+ scrollTrigger: {
10
+ trigger: item,
11
+ start: 'top 80%',
12
+ toggleActions: 'play none none reverse',
13
+ once: false, // 动画只播放一次
14
+ },
15
+ opacity: 0,
16
+ y: 80,
17
+ duration: 0.4,
18
+ ease: 'power2.out',
19
+ });
20
+ });
21
+ })();
22
+
23
+ // 从左往右显示
24
+ (function () {
25
+ const fadeDom = document.querySelectorAll('.fade-in-from-left-content');
26
+ fadeDom.forEach((item) => {
27
+ gsap.from(item, {
28
+ scrollTrigger: {
29
+ trigger: item,
30
+ start: 'top 80%',
31
+ toggleActions: 'play none none reverse',
32
+ once: false, // 动画只播放一次
33
+ },
34
+ opacity: 0,
35
+ x: -80,
36
+ duration: 0.4,
37
+ ease: 'power1.out',
38
+ });
39
+ });
40
+ })();
41
+
42
+ // 从右往左显示
43
+ (function () {
44
+ const fadeDom = document.querySelectorAll('.fade-in-from-right-content');
45
+ fadeDom.forEach((item) => {
46
+ gsap.from(item, {
47
+ scrollTrigger: {
48
+ trigger: item,
49
+ start: 'top 80%',
50
+ toggleActions: 'play none none reverse',
51
+ once: false, // 动画只播放一次
52
+ },
53
+ opacity: 0,
54
+ x: 80,
55
+ duration: 0.4,
56
+ ease: 'power1.out',
57
+ });
58
+ });
59
+ })();
60
+
61
+ // 跟随滚动缓慢显示
62
+ (function () {
63
+ const fadeDom = document.querySelectorAll('.slow-reveal-content');
64
+ fadeDom.forEach((item) => {
65
+ gsap.from(item, {
66
+ scrollTrigger: {
67
+ trigger: item,
68
+ start: 'top 80%',
69
+ end: 'top 60%',
70
+ toggleActions: 'play none none reverse',
71
+ scrub: 1, // 平滑跟随滚动
72
+ },
73
+ opacity: 1,
74
+ y: 100,
75
+ duration: 0.4,
76
+ ease: 'power1.out',
77
+ });
78
+ });
79
+ })();
80
+
81
+ // 按序从下显示(group)
82
+ const el = document.querySelectorAll('.fade-in-box');
83
+ el.forEach((item) => {
84
+ // 过滤出不包含 no-fade-in 类名的子元素
85
+ const children = Array.from(item.children).filter(
86
+ (child) => !child.classList.contains('no-fade-in')
87
+ );
88
+ gsap.from(children, {
89
+ scrollTrigger: {
90
+ trigger: item,
91
+ start: 'top 80%',
92
+ toggleActions: 'play none none reverse',
93
+ once: false, // 动画只播放一次
94
+ },
95
+ opacity: 0,
96
+ y: 80,
97
+ duration: 0.4,
98
+ stagger: 0.2,
99
+ ease: 'power2.out',
100
+ });
101
+ });
102
+
103
+ // 按序从左进入显示
104
+ const fromLeft = document.querySelectorAll('.fade-in-from-left');
105
+ fromLeft.forEach((item) => {
106
+ // 过滤出不包含 no-fade-in 类名的子元素
107
+ const children = Array.from(item.children).filter(
108
+ (child) => !child.classList.contains('no-fade-in')
109
+ );
110
+ gsap.from(children, {
111
+ scrollTrigger: {
112
+ trigger: item,
113
+ start: 'top 80%',
114
+ toggleActions: 'play none none reverse',
115
+ once: false, // 动画只播放一次
116
+ },
117
+ opacity: 0,
118
+ x: -80,
119
+ duration: 0.4,
120
+ stagger: 0.1,
121
+ ease: 'power1.out',
122
+ });
123
+ });
124
+
125
+ // 按序从右进入显示
126
+ const fromRight = document.querySelectorAll('.fade-in-from-right');
127
+ fromRight.forEach((item) => {
128
+ // 过滤出不包含 no-fade-in 类名的子元素
129
+ const children = Array.from(item.children).filter(
130
+ (child) => !child.classList.contains('no-fade-in')
131
+ );
132
+ gsap.from(children, {
133
+ scrollTrigger: {
134
+ trigger: item,
135
+ start: 'top 80%',
136
+ toggleActions: 'play none none reverse',
137
+ once: false,
138
+ },
139
+ opacity: 0,
140
+ x: 80,
141
+ duration: 0.4,
142
+ stagger: 0.1,
143
+ ease: 'power1.out',
144
+ });
145
+ });
146
+ });
147
+
148
+ // 跟随滚动缓慢显示
149
+ const slowReveal = document.querySelectorAll('.slow-reveal');
150
+ slowReveal.forEach((element) => {
151
+ // 过滤出不包含 no-fade-in 类名的子元素
152
+ const children = Array.from(element.children).filter(
153
+ (child) => !child.classList.contains('no-fade-in')
154
+ );
155
+ gsap.from(children, {
156
+ scrollTrigger: {
157
+ trigger: element,
158
+ start: 'top 80%',
159
+ end: 'top 60%',
160
+ scrub: 1, // 平滑跟随滚动
161
+ toggleActions: 'play none none reverse',
162
+ },
163
+ opacity: 1,
164
+ y: 100,
165
+ duration: 0.4,
166
+ stagger: 0.1,
167
+ ease: 'power1.out',
168
+ });
169
+ });