gsap的ScrollTrigger让你的页面更炫酷

之前做官网,设计的交互虽然在其他网站很常见,但是我一时不知道如何实现,直到我看到了gsap,发现原来这么简单。

项目搭建

1. 创建vite项目,并安装依赖

# 创建一个原生ts项目
pnpm create vite gsap-demo --template vanilla-ts
cd gsap-demo

# 安装gsap依赖
pnpm add gsap

2. 初始化gsap

import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

效果一:横向滚动

滚动页面滚动条,gsap会接管滚动条,进行div的横向滚动。

image.png

1. 编写html

父组件flex布局,子元素设置三个图片。

<div class="box-container">
    <div class="box">
    <img class="box-image" src="https://picsum.photos/1200/900" alt="box" />
    </div>
    <div class="box">
    <img class="box-image" src="https://picsum.photos/1200/900" alt="box" />
    </div>
    <div class="box">
    <img class="box-image" src="https://picsum.photos/1200/900" alt="box" />
    </div>
</div>
.box-container {
  display: flex;
  flex-wrap: nowrap;
  gap: 20px;
  overflow: hidden;
}

.box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100vh;
  flex-shrink: 0;
}

.box-image {
  object-fit: cover;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  border-radius: 10px;
}

2. 配置gsap

const boxContainer: HTMLElement | null = document.querySelector('.box-container')
  const boxItems = gsap.utils.toArray('.box-container .box')
  if (!boxContainer) return
  gsap.to(boxItems, {
    xPercent: -100 * (boxItems.length - 1),
    ease: 'none',
    scrollTrigger: {
      trigger: boxContainer,
      pin: true,
      start: 'top top',
      scrub: 1,
      markers: true,
      end: `+=${boxContainer.offsetWidth || 0 - innerWidth}`,
    },
  })

详细说明:

  • xPercent: -100 (boxItems.length - 1): 这行代码设置了每个 boxItems 元素的水平移动百分比。xPercent 是一个相对移动的值,-100 (boxItems.length - 1) 意味着将所有的 boxItems 元素水平移动到最后一个元素的位置。
  • ease: 'none': 这里设置了动画的缓动效果为“无”,即动画将以线性方式进行,没有加速或减速。
  • scrollTrigger: 这是 ScrollTrigger 插件的配置对象,用于定义滚动触发的行为。
    • trigger: boxContainer: 指定哪个元素触发滚动动画。
    • pin: true: 将 boxContainer 固定在视口中,直到动画结束。
    • start: 'top top': 定义动画开始的滚动位置,当 boxContainer 的顶部与视口顶部对齐时开始。
    • scrub: 1: 使动画与滚动同步,值为 1 表示动画的平滑度。
    • markers: true: 显示滚动触发器的标记,方便调试。
    • end: +=${boxContainer.offsetWidth || 0 - innerWidth}: 定义动画结束的滚动位置,计算方式是 boxContainer 的宽度减去视口的宽度。这段代码的目的是在用户滚动页面时,创建一个水平滚动的动画效果,使得 boxItems 元素在 boxContainer 内水平移动。

3. 查看效果

设置了的start: 'top top'后,可以看到marker的scroller-startscroller-end都在视口的顶部。

当marker的start移动到scroller-start后则开始动画。

image.png

当marker的end移动到scroller-end后则结束动画

image.png

效果二:卡片效果

滚动页面,卡片从右往左展示,类似卡片切换效果。

image.png

1. 编写html

绝对定位card,让他们交错排布。

<div class="card-container">
    <div class="card card-1">
    <img class="card-image" src="https://picsum.photos/400/300" alt="card" />
    </div>
    <div class="card card-2">
    <img class="card-image" src="https://picsum.photos/400/300" alt="card" />
    </div>
    <div class="card card-3">
    <img class="card-image" src="https://picsum.photos/400/300" alt="card" />
    </div>
    <div class="card card-4">
    <img class="card-image" src="https://picsum.photos/400/300" alt="card" />
    </div>
    <div class="card card-5">
    <img class="card-image" src="https://picsum.photos/400/300" alt="card" />
    </div>
</div>
.card-container {
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  gap: 20px;
  overflow: hidden;
  width: 100%;
  height: 100vh;
}

.card {
  width: 400px;
  height: 300px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  flex-shrink: 0;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
  border-radius: 10px;
  border: 2px solid #ccc;
  overflow: hidden;
}

.card-1 {
  right: 10%;
}

.card-2 {
  right: 12%;
}

.card-3 {
  right: 14%;
}

.card-4 {
  right: 16%;
}

.card-5 {
  right: 18%;
}

2. 编写gsap动画

const cardContainer: HTMLElement | null = document.querySelector('.card-container')
  if (!cardContainer) return
  gsap.timeline({
    scrollTrigger: {
      trigger: cardContainer,
      pin: true,
      start: 'top top',
      scrub: 1,
      end: `+=${cardContainer.offsetWidth || 0 - innerWidth}`,
      markers: true,
    },
  })
    .to('.card-5', { xPercent: -110, scale: 1.1 }, 0)
    .to('.card-5', { xPercent: -250, scale: 1 }, 1)
    .to('.card-4', { xPercent: -110, scale: 1.1 }, 1)
    .to('.card-4', { xPercent: -250, scale: 1 }, 2)
    .to('.card-3', { xPercent: -110, scale: 1.1 }, 2)
    .to('.card-3', { xPercent: -250, scale: 1 }, 3)
    .to('.card-2', { xPercent: -110, scale: 1.1 }, 3)
    .to('.card-2', { xPercent: -250, scale: 1 }, 4)
    .to('.card-1', { xPercent: -110, scale: 1.1 }, 4)
    .to('.card-1', { xPercent: -250, scale: 1 }, 5)

详细说明:

  • gsap.timeline: 创建一个时间轴动画,允许多个动画按顺序执行
  • gsap.timeline.to: 创建每个时间点的动画详情,例如本效果,就是每个卡片向左移动一定百分比和放大缩小效果。

3.查看效果

主要就是最后右边移动到中间并放大,然后移动到最左边缩小到正常大小,每个card依次执行。

image.png

总结

主要还是要多看文档,然后通过makers来确定滚动位置是否正确。尤其是结合整个页面时,要保证页面的高度时刻确定的,这样才能让页面加载完毕后,gsap的makers计算正确,比如之前设置了图片懒加载,但是忘了设置图片的高度,导致下面的gsap计算错误,滚动效果出现问题,这个时候就需要开启markers来确定问题。

参考文档

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容