Built to Move: 深入解析Eduard Bodak作品集的动画实现
本文通过Eduard Bodak的实战演练,详细解析了其作品集中三种核心GSAP动画的实现方式:滚动触发的3D卡片翻转、鼠标移动交互卡片和圆形布局的滚动旋转效果。
技术架构概述
项目采用Locomotive Scroll V5处理滚动进度和视口检测,利用其内置的data-scroll-offset和data-scroll-event-progress属性实现元素进度追踪。通过CSS变量--progress(范围0-1)直接驱动动画,避免与GSAP的ScrollTrigger功能重叠。
1
2
3
4
5
|
// Locomotive Scroll进度事件监听示例
window.addEventListener("progressHero", (e) => {
const { progress } = e.detail;
this.timeline?.progress(progress);
});
|
三大动画技术详解
1. 滚动触发的3D卡片翻转
结构设计
1
2
3
4
5
6
|
<section data-scroll data-scroll-offset="0%,25%" data-scroll-event-progress="progressHero">
<div class="card" data-hero-animation-card>
<div class="card_front">...</div>
<div class="card_back">...</div>
</div>
</section>
|
时间线控制逻辑
- 使用
requestAnimationFrame()避免布局抖动
- 创建暂停的时间线由Locomotive控制进度
- 为每张卡设置独特的Y轴偏移和Z轴旋转值
1
2
3
4
5
6
7
8
9
10
11
12
13
|
computeDesktopTimeline() {
this.timeline = gsap.timeline({ paused: true });
this.heroCards.forEach((card, index) => {
this.timeline.to(card, {
force3D: true,
keyframes: {
"75%": { x: () => -position * (card.offsetWidth * 0.9), rotationZ: values[index] },
"100%": { y: () => targetY - yOffsets[index], scale: 0.85, rotateX: -16 }
}
}, index * 0.012);
});
}
|
浮动效果增强
1
2
3
4
5
6
7
|
gsap.fromTo(element, { yPercent: -3 }, {
yPercent: 3,
duration: () => gsap.utils.random(1.5, 2.5),
ease: "sine.inOut",
repeat: -1,
repeatRefresh: true
});
|
2. 鼠标移动交互卡片
初始化动画
1
2
3
4
5
6
7
8
|
this.introTimeline.fromTo(this.card, {
rotationZ: 0, rotationY: -90, y: "-4em"
}, {
rotationZ: 6, rotationY: 0, y: "0em",
duration: 1,
ease: "elastic.out(1,0.75)",
onComplete: () => this.initAnimation()
});
|
鼠标移动处理
1
2
3
4
5
6
7
8
9
10
11
12
|
mouseMovement() {
const normalizedX = (mouseX - this.centerX) / this.centerX;
const rotationY = normalizedX * this.rotationFactor;
const rotationZ = 6 - rotationProgress * 12;
gsap.to(this.card, {
rotationY: rotationY,
rotationZ: rotationZ,
duration: 0.5,
ease: "power2.out"
});
}
|
无障碍支持
通过媒体查询确保动画仅在支持鼠标设备和未开启减少运动选项时启用:
1
2
3
|
gsap.matchMedia().add("(hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)", () => {
// 鼠标动画逻辑
});
|
3. 圆形布局滚动旋转
CSS结构设计
1
2
3
4
5
|
<div class="wheel" style="--wheel-angle: 15deg">
<div class="wheel_item-wrap" style="--wheel-index: 0">
<div class="wheel_item">...</div>
</div>
</div>
|
CSS变换实现
1
2
3
4
5
6
7
8
9
10
|
.wheel_item-wrap {
transform: rotate(calc(var(--wheel-angle) * var(--wheel-index)));
grid-area: 1 / 1;
}
.wheel_item {
transform: translateY(-100%);
aspect-ratio: 60 / 83;
width: 7.5em;
}
|
GSAP滚动控制
1
2
|
this.timeline = gsap.timeline({ paused: true });
this.timeline.to(this.wheel, { rotate: -65, duration: 1, ease: "linear" });
|
性能优化与最佳实践
- 响应式适配:使用
gsap.matchMedia()为不同视口创建独立时间线
- 资源清理:在重建时间线前清除旧的GSAP内联样式
- 进度管理:通过Locomotive的CSS变量实现精细的动画触发控制
- 用户体验:为减少运动偏好的用户提供简化动画版本
开发心得与资源推荐
Eduard分享道:“这个项目成为了我的个人学习 playground,充分证明了通过实践构建想象中的效果是最好的学习方式。”
推荐学习资源:
- Codrops案例研究
- GSAP官方文档和CodePen示例
- jhey的CSS技巧和GSAP实践
- Timothy Ricks的YouTube教程
- Osmo的交互资源
技术总结
本文演示了如何结合Locomotive Scroll、GSAP和CSS变量创建高性能的滚动驱动和交互式动画。关键要点包括:利用数据属性进行进度控制、使用关键帧实现复杂动画序列、通过媒体查询确保无障碍访问,以及如何为不同设备类型优化动画体验。
这种技术组合为现代网页动画提供了强大的实现方案,既保证了视觉效果,又确保了性能和可访问性。