gsap-scrolltrigger
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGSAP ScrollTrigger
GSAP ScrollTrigger
Scroll-driven animations and interactions.
基于滚动的动画与交互效果。
Quick Start
快速开始
bash
npm install gsapjavascript
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
gsap.to('.box', {
x: 500,
scrollTrigger: {
trigger: '.box',
start: 'top center',
end: 'bottom center',
scrub: true
}
});bash
npm install gsapjavascript
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
gsap.to('.box', {
x: 500,
scrollTrigger: {
trigger: '.box',
start: 'top center',
end: 'bottom center',
scrub: true
}
});Core Concepts
核心概念
Basic ScrollTrigger
基础ScrollTrigger使用
javascript
gsap.to('.element', {
x: 200,
scrollTrigger: {
trigger: '.element', // Element that triggers the animation
start: 'top center', // When trigger hits viewport center
end: 'bottom center', // When trigger leaves viewport center
toggleActions: 'play pause resume reset'
}
});javascript
gsap.to('.element', {
x: 200,
scrollTrigger: {
trigger: '.element', // Element that triggers the animation
start: 'top center', // When trigger hits viewport center
end: 'bottom center', // When trigger leaves viewport center
toggleActions: 'play pause resume reset'
}
});Start/End Positions
起始/结束位置
javascript
// Format: "trigger-position viewport-position"
start: 'top center' // Trigger's top hits viewport center
start: 'top 80%' // Trigger's top hits 80% down viewport
start: 'center center' // Trigger's center hits viewport center
start: 'bottom top' // Trigger's bottom hits viewport top
start: 'top top+=100' // Trigger's top hits 100px below viewport topjavascript
// Format: "trigger-position viewport-position"
start: 'top center' // Trigger's top hits viewport center
start: 'top 80%' // Trigger's top hits 80% down viewport
start: 'center center' // Trigger's center hits viewport center
start: 'bottom top' // Trigger's bottom hits viewport top
start: 'top top+=100' // Trigger's top hits 100px below viewport topPosition Reference
位置参考
| Value | Description |
|---|---|
| Top edge |
| Center |
| Bottom edge |
| 80% from top |
| Plus 100 pixels |
| Minus 50 pixels |
| Value | Description |
|---|---|
| Top edge |
| Center |
| Bottom edge |
| 80% from top |
| Plus 100 pixels |
| Minus 50 pixels |
Scrub Animations
滚动同步动画
Basic Scrub
基础滚动同步
javascript
// Animation progress tied to scroll position
gsap.to('.progress-bar', {
scaleX: 1,
scrollTrigger: {
trigger: '.content',
start: 'top top',
end: 'bottom bottom',
scrub: true // Directly linked to scroll
}
});javascript
// Animation progress tied to scroll position
gsap.to('.progress-bar', {
scaleX: 1,
scrollTrigger: {
trigger: '.content',
start: 'top top',
end: 'bottom bottom',
scrub: true // Directly linked to scroll
}
});Smooth Scrub
平滑滚动同步
javascript
gsap.to('.element', {
x: 500,
scrollTrigger: {
trigger: '.section',
scrub: 1, // 1 second smoothing
// scrub: 0.5 // 0.5 second smoothing
// scrub: 2 // 2 second smoothing (laggy feel)
}
});javascript
gsap.to('.element', {
x: 500,
scrollTrigger: {
trigger: '.section',
scrub: 1, // 1 second smoothing
// scrub: 0.5 // 0.5 second smoothing
// scrub: 2 // 2 second smoothing (laggy feel)
}
});Scrub with Timeline
时间轴滚动同步
javascript
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.container',
start: 'top top',
end: '+=3000', // Scroll distance
scrub: 1,
pin: true
}
});
tl.to('.step1', { opacity: 1 })
.to('.step2', { opacity: 1 })
.to('.step3', { opacity: 1 });javascript
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.container',
start: 'top top',
end: '+=3000', // Scroll distance
scrub: 1,
pin: true
}
});
tl.to('.step1', { opacity: 1 })
.to('.step2', { opacity: 1 })
.to('.step3', { opacity: 1 });Pinning
元素固定
Basic Pin
基础固定
javascript
ScrollTrigger.create({
trigger: '.panel',
start: 'top top',
end: '+=500', // Pin for 500px of scroll
pin: true
});javascript
ScrollTrigger.create({
trigger: '.panel',
start: 'top top',
end: '+=500', // Pin for 500px of scroll
pin: true
});Pin with Animation
固定与动画结合
javascript
gsap.to('.content', {
x: '-200%',
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-section',
start: 'top top',
end: () => '+=' + document.querySelector('.horizontal-section').offsetWidth,
pin: true,
scrub: 1
}
});javascript
gsap.to('.content', {
x: '-200%',
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-section',
start: 'top top',
end: () => '+=' + document.querySelector('.horizontal-section').offsetWidth,
pin: true,
scrub: 1
}
});Pin Spacing
固定间距设置
javascript
ScrollTrigger.create({
trigger: '.section',
pin: true,
pinSpacing: true, // Default: adds space for pinned duration
// pinSpacing: false // No extra space (content overlaps)
// pinSpacing: '500px' // Custom spacing
});javascript
ScrollTrigger.create({
trigger: '.section',
pin: true,
pinSpacing: true, // Default: adds space for pinned duration
// pinSpacing: false // No extra space (content overlaps)
// pinSpacing: '500px' // Custom spacing
});Toggle Actions
切换动作
Action Syntax
动作语法
javascript
// Format: "onEnter onLeave onEnterBack onLeaveBack"
toggleActions: 'play pause resume reset'
// Common combinations:
toggleActions: 'play none none none' // Play once
toggleActions: 'play reverse play reverse' // Toggle direction
toggleActions: 'restart none none none' // Restart each time
toggleActions: 'play complete reverse reset'javascript
// Format: "onEnter onLeave onEnterBack onLeaveBack"
toggleActions: 'play pause resume reset'
// Common combinations:
toggleActions: 'play none none none' // Play once
toggleActions: 'play reverse play reverse' // Toggle direction
toggleActions: 'restart none none none' // Restart each time
toggleActions: 'play complete reverse reset'Action Values
动作取值
| Action | Effect |
|---|---|
| Play forward |
| Pause |
| Resume from paused |
| Play backward |
| Restart from beginning |
| Reset to start (no animation) |
| Jump to end |
| Do nothing |
| Action | Effect |
|---|---|
| Play forward |
| Pause |
| Resume from paused |
| Play backward |
| Restart from beginning |
| Reset to start (no animation) |
| Jump to end |
| Do nothing |
Snap Points
吸附点
Basic Snap
基础吸附
javascript
ScrollTrigger.create({
trigger: '.sections',
start: 'top top',
end: 'bottom bottom',
snap: 1 / 4 // Snap to quarters
});javascript
ScrollTrigger.create({
trigger: '.sections',
start: 'top top',
end: 'bottom bottom',
snap: 1 / 4 // Snap to quarters
});Snap to Labels
吸附到标签
javascript
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.container',
scrub: 1,
snap: {
snapTo: 'labels',
duration: 0.5,
ease: 'power2.inOut'
}
}
});
tl.addLabel('intro')
.to('.a', { opacity: 1 })
.addLabel('middle')
.to('.b', { opacity: 1 })
.addLabel('end');javascript
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.container',
scrub: 1,
snap: {
snapTo: 'labels',
duration: 0.5,
ease: 'power2.inOut'
}
}
});
tl.addLabel('intro')
.to('.a', { opacity: 1 })
.addLabel('middle')
.to('.b', { opacity: 1 })
.addLabel('end');Snap Configuration
吸附配置
javascript
snap: {
snapTo: [0, 0.25, 0.5, 0.75, 1], // Snap to specific points
duration: { min: 0.2, max: 0.6 }, // Snap duration range
delay: 0, // Delay before snap
ease: 'power1.inOut', // Snap easing
directional: true // Snap in scroll direction
}javascript
snap: {
snapTo: [0, 0.25, 0.5, 0.75, 1], // Snap to specific points
duration: { min: 0.2, max: 0.6 }, // Snap duration range
delay: 0, // Delay before snap
ease: 'power1.inOut', // Snap easing
directional: true // Snap in scroll direction
}Callbacks
回调函数
ScrollTrigger Callbacks
ScrollTrigger回调
javascript
ScrollTrigger.create({
trigger: '.section',
onEnter: () => console.log('Entered'),
onLeave: () => console.log('Left'),
onEnterBack: () => console.log('Entered from bottom'),
onLeaveBack: () => console.log('Left going up'),
onUpdate: (self) => console.log('Progress:', self.progress),
onToggle: (self) => console.log('Active:', self.isActive),
onRefresh: () => console.log('Refreshed')
});javascript
ScrollTrigger.create({
trigger: '.section',
onEnter: () => console.log('Entered'),
onLeave: () => console.log('Left'),
onEnterBack: () => console.log('Entered from bottom'),
onLeaveBack: () => console.log('Left going up'),
onUpdate: (self) => console.log('Progress:', self.progress),
onToggle: (self) => console.log('Active:', self.isActive),
onRefresh: () => console.log('Refreshed')
});Progress-Based Updates
基于进度的更新
javascript
ScrollTrigger.create({
trigger: '.section',
start: 'top bottom',
end: 'bottom top',
onUpdate: (self) => {
// self.progress: 0 to 1
// self.direction: 1 (down) or -1 (up)
// self.velocity: scroll speed
updateElement(self.progress);
}
});javascript
ScrollTrigger.create({
trigger: '.section',
start: 'top bottom',
end: 'bottom top',
onUpdate: (self) => {
// self.progress: 0 to 1
// self.direction: 1 (down) or -1 (up)
// self.velocity: scroll speed
updateElement(self.progress);
}
});Parallax Effects
视差效果
Basic Parallax
基础视差
javascript
// Background moves slower than scroll
gsap.to('.background', {
yPercent: -50,
ease: 'none',
scrollTrigger: {
trigger: '.section',
scrub: true
}
});
// Foreground moves faster
gsap.to('.foreground', {
yPercent: 50,
ease: 'none',
scrollTrigger: {
trigger: '.section',
scrub: true
}
});javascript
// Background moves slower than scroll
gsap.to('.background', {
yPercent: -50,
ease: 'none',
scrollTrigger: {
trigger: '.section',
scrub: true
}
});
// Foreground moves faster
gsap.to('.foreground', {
yPercent: 50,
ease: 'none',
scrollTrigger: {
trigger: '.section',
scrub: true
}
});Multi-Layer Parallax
多层视差
javascript
const layers = [
{ selector: '.layer-1', speed: -20 },
{ selector: '.layer-2', speed: -40 },
{ selector: '.layer-3', speed: -60 },
{ selector: '.layer-4', speed: -80 }
];
layers.forEach(layer => {
gsap.to(layer.selector, {
yPercent: layer.speed,
ease: 'none',
scrollTrigger: {
trigger: '.parallax-section',
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
});javascript
const layers = [
{ selector: '.layer-1', speed: -20 },
{ selector: '.layer-2', speed: -40 },
{ selector: '.layer-3', speed: -60 },
{ selector: '.layer-4', speed: -80 }
];
layers.forEach(layer => {
gsap.to(layer.selector, {
yPercent: layer.speed,
ease: 'none',
scrollTrigger: {
trigger: '.parallax-section',
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
});Horizontal Scrolling
横向滚动
Horizontal Section
横向区块
javascript
const sections = gsap.utils.toArray('.panel');
gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-container',
pin: true,
scrub: 1,
snap: 1 / (sections.length - 1),
end: () => '+=' + document.querySelector('.horizontal-container').offsetWidth
}
});javascript
const sections = gsap.utils.toArray('.panel');
gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: 'none',
scrollTrigger: {
trigger: '.horizontal-container',
pin: true,
scrub: 1,
snap: 1 / (sections.length - 1),
end: () => '+=' + document.querySelector('.horizontal-container').offsetWidth
}
});Markers (Development)
标记(开发调试)
javascript
ScrollTrigger.create({
trigger: '.section',
start: 'top center',
end: 'bottom center',
markers: true, // Show visual markers
// markers: { startColor: 'green', endColor: 'red', fontSize: '12px' }
});javascript
ScrollTrigger.create({
trigger: '.section',
start: 'top center',
end: 'bottom center',
markers: true, // Show visual markers
// markers: { startColor: 'green', endColor: 'red', fontSize: '12px' }
});Batch Animations
批量动画
Stagger on Scroll
滚动时 stagger 动画
javascript
ScrollTrigger.batch('.card', {
onEnter: (elements) => {
gsap.from(elements, {
opacity: 0,
y: 50,
stagger: 0.1,
duration: 0.5
});
},
start: 'top 85%'
});javascript
ScrollTrigger.batch('.card', {
onEnter: (elements) => {
gsap.from(elements, {
opacity: 0,
y: 50,
stagger: 0.1,
duration: 0.5
});
},
start: 'top 85%'
});Batch Configuration
批量配置
javascript
ScrollTrigger.batch('.item', {
interval: 0.1, // Time between batches
batchMax: 3, // Max items per batch
onEnter: batch => gsap.to(batch, { opacity: 1, y: 0, stagger: 0.1 }),
onLeave: batch => gsap.to(batch, { opacity: 0, y: 20 }),
onEnterBack: batch => gsap.to(batch, { opacity: 1, y: 0 }),
onLeaveBack: batch => gsap.to(batch, { opacity: 0, y: -20 })
});javascript
ScrollTrigger.batch('.item', {
interval: 0.1, // Time between batches
batchMax: 3, // Max items per batch
onEnter: batch => gsap.to(batch, { opacity: 1, y: 0, stagger: 0.1 }),
onLeave: batch => gsap.to(batch, { opacity: 0, y: 20 }),
onEnterBack: batch => gsap.to(batch, { opacity: 1, y: 0 }),
onLeaveBack: batch => gsap.to(batch, { opacity: 0, y: -20 })
});Common Patterns
常见模式
Reveal on Scroll
滚动时渐显
javascript
gsap.utils.toArray('.reveal').forEach(elem => {
gsap.from(elem, {
opacity: 0,
y: 50,
duration: 0.8,
scrollTrigger: {
trigger: elem,
start: 'top 80%',
toggleActions: 'play none none none'
}
});
});javascript
gsap.utils.toArray('.reveal').forEach(elem => {
gsap.from(elem, {
opacity: 0,
y: 50,
duration: 0.8,
scrollTrigger: {
trigger: elem,
start: 'top 80%',
toggleActions: 'play none none none'
}
});
});Progress Indicator
进度指示器
javascript
gsap.to('.progress-bar', {
scaleX: 1,
transformOrigin: 'left center',
ease: 'none',
scrollTrigger: {
trigger: 'body',
start: 'top top',
end: 'bottom bottom',
scrub: 0.3
}
});javascript
gsap.to('.progress-bar', {
scaleX: 1,
transformOrigin: 'left center',
ease: 'none',
scrollTrigger: {
trigger: 'body',
start: 'top top',
end: 'bottom bottom',
scrub: 0.3
}
});Sticky Header Transform
粘性头部变换
javascript
ScrollTrigger.create({
start: 'top -80',
onUpdate: (self) => {
if (self.direction === 1) {
gsap.to('.header', { y: -80, duration: 0.3 });
} else {
gsap.to('.header', { y: 0, duration: 0.3 });
}
}
});javascript
ScrollTrigger.create({
start: 'top -80',
onUpdate: (self) => {
if (self.direction === 1) {
gsap.to('.header', { y: -80, duration: 0.3 });
} else {
gsap.to('.header', { y: 0, duration: 0.3 });
}
}
});Temporal Collapse Patterns
时间折叠模式
Countdown Scroll Reveal
滚动渐显倒计时
javascript
// Reveal countdown sections as user scrolls
const sections = ['days', 'hours', 'minutes', 'seconds'];
sections.forEach((section, i) => {
gsap.from(`.countdown-${section}`, {
opacity: 0,
scale: 0.8,
y: 50,
duration: 0.8,
ease: 'power3.out',
scrollTrigger: {
trigger: `.countdown-${section}`,
start: 'top 80%',
toggleActions: 'play none none none'
}
});
});javascript
// Reveal countdown sections as user scrolls
const sections = ['days', 'hours', 'minutes', 'seconds'];
sections.forEach((section, i) => {
gsap.from(`.countdown-${section}`, {
opacity: 0,
scale: 0.8,
y: 50,
duration: 0.8,
ease: 'power3.out',
scrollTrigger: {
trigger: `.countdown-${section}`,
start: 'top 80%',
toggleActions: 'play none none none'
}
});
});Scroll-Based Time Dilation Effect
基于滚动的时间膨胀效果
javascript
gsap.timeline({
scrollTrigger: {
trigger: '.time-section',
start: 'top center',
end: 'bottom center',
scrub: 1
}
})
.to('.time-digit', {
textShadow: '0 0 50px #00F5FF, 0 0 100px #00F5FF',
scale: 1.1
})
.to('.particles', {
opacity: 1,
filter: 'blur(0px)'
}, '<');javascript
gsap.timeline({
scrollTrigger: {
trigger: '.time-section',
start: 'top center',
end: 'bottom center',
scrub: 1
}
})
.to('.time-digit', {
textShadow: '0 0 50px #00F5FF, 0 0 100px #00F5FF',
scale: 1.1
})
.to('.particles', {
opacity: 1,
filter: 'blur(0px)'
}, '<');Performance Tips
性能优化建议
javascript
// Disable on mobile if needed
ScrollTrigger.matchMedia({
'(min-width: 768px)': function() {
// Desktop animations
},
'(max-width: 767px)': function() {
// Simpler mobile animations
}
});
// Refresh on resize
ScrollTrigger.refresh();
// Kill all ScrollTriggers
ScrollTrigger.killAll();
// Kill specific trigger
const st = ScrollTrigger.create({ ... });
st.kill();javascript
// Disable on mobile if needed
ScrollTrigger.matchMedia({
'(min-width: 768px)': function() {
// Desktop animations
},
'(max-width: 767px)': function() {
// Simpler mobile animations
}
});
// Refresh on resize
ScrollTrigger.refresh();
// Kill all ScrollTriggers
ScrollTrigger.killAll();
// Kill specific trigger
const st = ScrollTrigger.create({ ... });
st.kill();Reference
参考资料
- See for animation basics
gsap-fundamentals - See for timeline composition
gsap-sequencing - See for React integration with ScrollTrigger
gsap-react
- 动画基础请参考
gsap-fundamentals - 时间轴组合请参考
gsap-sequencing - React集成ScrollTrigger请参考
gsap-react