首页 / 中文教程 / 教程

Bricks 中入门 GSAP(用 data 属性在构建器里管理动画)

本教程教你如何在 Bricks Builder 里,用特定 data 属性中的 JSON 对象运行基础 GSAP 动画。

Ray Chan·2026-08-12·约 6 分钟

本教程教你如何在 Bricks Builder 里,用特定 data 属性中的 JSON 对象运行基础 GSAP 动画。

不是所有人都喜欢动画。但如果你和我一样喜欢——GSAP 就是 JavaScript 生态里 #1 必学库

GSAP 是高级前端开发者使用的复杂库。要发挥它的全部潜力,你需要扎实的 JavaScript 功底。但如果我们能简化流程,直接在 Bricks Builder 里管理这个库呢?

这就是本教程的目标:带你入门 GSAP 的基础,并提供一组属性,让你在构建器里轻松管理 tween 和 timeline。

这种做法的优势:

  • JavaScript Helper 极其轻量,不会对网站性能造成负面影响。
  • 兼容所有 GSAP 参数和大多数(甚至全部)GSAP 插件,包括流行的 ScrollTrigger 插件。
  • 不需要为每个页面单独处理 init 文件或内联代码——所有选项都在构建器里管理。
  • 熟悉这些属性之后,设置 tween 和 timeline 只是几分钟的事。
  • 顺便还能学到一点 JavaScript/JSON 的逻辑。

加载 GSAP 库

在这个页面下载库:https://greensock.com/docs/v3/Installation。把压缩版 gsap.min.js 上传到子主题并加载。

如果打算用 ScrollTrigger 插件,记得把 ScrollTrigger.min.js 也上传并加载。

作者偏好的脚本加载方式见这篇文章

JavaScript

确保下面的代码在 GSAP 库(以及所有插件)初始化之后运行:

// Register the GSAP Plugin
gsap.registerPlugin(ScrollTrigger);

// Run the script after the DOM content is loaded
window.addEventListener('DOMContentLoaded', () => {

   // Tweens
   const gsapTweens = document.querySelectorAll('[data-tween]');
   const tweenFn = (arr) => {
      // Loop into each tween
      arr.forEach(tween => {

         // Get the tween type
         const type = tween.dataset.tween;

         let selector = tween;
         if (tween.dataset.tweenSelector) selector = tween.dataset.tweenSelector;

         // Get the tween option parameters
         const options = JSON.parse(tween.dataset.tweenOptions);

         // Run the tween based on the type of the animation
         switch (type) {
            case "to":
               gsap.to(selector, options);
               break;
            case "from":
               gsap.from(selector, options);
               break;
            case "fromTo":
               gsap.fromTo(selector, options.from, options.to);
               break;
         };
      });
   }

   // Check if there are tweens on the page  
   if (gsapTweens.length > 0) tweenFn(gsapTweens);

   // Timeline
   const gsapContainers = document.querySelectorAll('[data-tl-container="true"]');

   const timelineFn = (arr) => {
      // Loop into each timeline container
      arr.forEach(container => {

         // Get the timeline name
         const containerName = container.dataset.tlName;

         // Get the timeline options if any
         let containerOptions;
         if (container.dataset.tlOptions) containerOptions = JSON.parse(container.dataset.tlOptions);

         // Create an Array where we'll store all the tween options
         let tweensOptions = [];

         // Query the nested tweens that are part the timeline
         const tweens = container.querySelectorAll('[data-tl-tween][data-tl-name=' + containerName + ']');
         tweens.forEach(tween => {

            // Get the Timeline name related to the tween
            const tweenTl = tween.dataset.tlName;

            // Get the tween type
            let tweenType = tween.dataset.tlTween;

            // Set the selector
            let tweenSelector = tween;
            if (tween.dataset.tlTweenSelector) tweenSelector = tween.dataset.tlTweenSelector;

            // Get the order of the tween inside the timeline. Default is 999.
            let tweenOrder = 999;
            if (tween.dataset.tlTweenOrder) tweenOrder = parseInt(tween.dataset.tlTweenOrder);

            // Get the position of the tween inside the timeline. Default is "-=0"
            let tweenPosition = "+=0";
            if (tween.dataset.tlTweenPosition) tweenPosition = tween.dataset.tlTweenPosition;

            // Get the tween options
            const tweenOptions = tween.dataset.tlTweenOptions;

            const splitOptions = tweenOptions.split(';');
            splitOptions.forEach(option => {
               option = JSON.parse(option);

               let options;
               if (option.options) options = option.options;

               // override selector
               let selector = tweenSelector;
               if (option.selector) selector = option.selector;

               // override order
               let order = tweenOrder;
               if (option.order) order = parseInt(option.order);

               // override position
               let position = tweenPosition;
               if (option.position) position = option.position;

               // override type
               let type = tweenType;
               if (option.type) type = option.type;

               // Push all our options inside an Array
               tweensOptions.push({
                  selector: selector,
                  timeline: tweenTl,
                  type: type,
                  options: options,
                  order: order,
                  position: position,
               })
            })
         })

         // Sort the array based on the order parameter
         tweensOptions = Object.values(tweensOptions).sort((a, b) => a.order - b.order);

         // Initialize the timeline
         const tl = gsap.timeline(containerOptions);

         // Loop inside our tween options Array
         tweensOptions.forEach(el => {

            // Add the tween to the timeline
            switch (el.type) {
               case "to":
                  tl.to(el.selector, el.options, el.position);
                  break;
               case "from":
                  tl.from(el.selector, el.options, el.position);
                  break;
               case "fromTo":
                  tl.fromTo(el.selector, el.options.from, el.options.to, el.position);
                  break;
            }
         })
      })
   }

   // Check if there are timelines set on the page
   if (gsapContainers.length > 0) timelineFn(gsapContainers);

})

注意这段代码的第一行:我们注册了 ScrollTrigger 插件。如果你不打算用它,可以删掉这一行;用同样的方式也可以注册其他 GSAP 插件。

在 Bricks 里添加动画

这一部分我们来学 GSAP 更常用的功能:

  • 设置简单的 tween(from / to / fromTo)
  • 创建 timeline 并向其中添加嵌套 tween
  • 用 ScrollTrigger 插件把这些动画绑定到滚动

Tweens(补间动画)

简单来说,tween 就是附着在目标(理解为网站上的一个元素)上的单个动画。单个 tween 可以同时动画多个参数:颜色、形状、尺寸、位置等。更多信息参考官方文档

from

可以把 gsap.from() 理解成反向 tween:你定义值从哪开始,然后它动画到当前状态。这非常适合把对象“动画进画面”——因为你可以先把元素摆成最终想要的样子,再从别处飞入。

官方文档

用我们的 JavaScript Helper 设置 from tween 非常简单:在想要动画的元素上创建一个叫 data-tween 的 data 属性,值填 from

下一步把所有参数作为一个 JSON 对象插入。推荐用这个免费的在线 JSON 格式化器来转换/校验 JSON。

下面是一个带动画参数的 JSON 对象示例:

{
   "right":"0",
   "rotation":"720",
   "borderRadius":"50%",
   "backgroundColor":"#2fff00",
   "duration":"2"
}

新建一个叫 data-tween-options 的 data 属性,把 JSON 对象粘进去:

搞定!刷新前端页面,页面加载完成后动画就会立刻运行。

to

最常见的动画类型是 to() tween,因为它允许你定义目标值(大多数人习惯“动画某个值”的思维方式)。

官方文档

to 动画和上面说的 “from” 动画运行方式完全一样,唯一区别是在 data-tween 属性里填 to

记住:from 设置动画的初始状态,to 设置最终状态——所以按需选择参数。

fromTo

gsap.fromTo() 让你同时定义动画的起始值和结束值(而 from() 和 to() 分别用当前状态作为起点或终点)。这对完全掌控动画非常有帮助,尤其是当它与其他动画链式组合时。

官方文档

要设置 fromTo 动画,把 data-tween 属性设为 fromTo

然后在 JSON 里同时包含 fromto 两个参数块。JSON 结构如下:

{
   "from":{
      ...
   },
   "to":{
      ...
   }
}

一个例子:

{
   "from":{
      "borderRadius":"0%",
      "backgroundColor":"#000000"
   },
   "to":{
      "right":"0",
      "rotation":"720",
      "borderRadius":"50%",
      "backgroundColor":"#2fff00",
      "duration":"2"
   }
}

把它粘进 data-tween-options 属性:

搞定!

全局选择器(可选)

默认情况下,动画作用在设置了属性的那个元素上。有些场景你想把动画应用到一个自定义选择器——比如某个 class——然后批量作用于所有匹配该选择器的元素。

为此我们引入了一个可选属性 data-tween-selector,值可以是任意自定义选择器:

有了这个可选属性,你就可以在页面上构建全局动画,不用给每个元素重复加同样的属性。它还解锁了更高级的功能,比如 staggers(错落动画)

Timelines(时间线)

Timeline 是强大的排序工具,作为 tween 和其他 timeline 的容器,方便把它们作为一个整体控制并精确管理时序。没有 Timeline,构建复杂序列会非常笨拙,因为你得给每个动画单独加 delay

官方文档

这里的思路是创建彼此关联的 tween。Timeline 在网页开发中的典型用法:按预定义顺序动画不同元素——比如先淡入区块的页眉,再淡入描述文字,然后放大行动召唤(CTA)按钮,最后揭示对应的图片。

用我们的 JavaScript Helper 创建 timeline:需要设置一个 timeline container(时间线容器),把所有嵌套 tween 关联到它。

来看具体怎么做。

容器

时间线容器是所有嵌套 tween 的父元素。可以设在任意 Bricks 元素上。DOM 结构如下:

tween 不要求是直接子元素,但必须是子元素

设置 timeline 只需要几个 data 属性。

data-tl-container

第一个属性是 data-tl-container,值为 true

data-tl-name

第二个必填属性是 data-tl-name。随便取个你喜欢的名字,比如 tl1timeline1headerTimeline

记住这个 timeline 的名字,后面要把相关 tween 关联到这个 timeline 时需要用到。

如果页面上要设置多个 timeline,务必给每个 timeline 取唯一的名字。

data-tl-options(可选)

还可以创建 data-tl-options 属性,用 JSON 对象给整个 timeline 设置全局参数:

这个属性是可选的。不加的话,timeline 使用 GSAP 默认值。

现在 timeline 设置好了,来给它加几个 tween!

嵌套 tween

在 timeline 里创建嵌套 tween,和上面单个 tween 的配置非常相似,只需插入对应的 timeline 名字来建立关联。

data-tl-name

在 tween 上填上之前设置在时间线容器上的 timeline 名字:

现在这个 tween 就是 timeline 的一部分了。同一 timeline 的所有 tween 都要加这个属性。

data-tl-tween-options

这和之前说的 data-tween-options 属性基本一样,但 JSON 结构略有修改:在 timeline 里,需要把参数包在一个 options 属性里:

JSON 结构如下:

{
   "options":{
      "...your parameters..."
   }
}

示例:

{
   "options":{
      "right":"0",
      "rotation":"720",
      "borderRadius":"50%",
      "backgroundColor":"#2fff00",
      "duration":"2"
   }
}

data-tl-tween

这和单个 tween 的 data-tween 属性完全一样:接受 tofromfromTo 三个值。

当同一元素上要处理多个 tween 时,可以在 JSON 对象里通过 type 属性覆盖这个值:

{
   "options":{
      "right":"0",
      "rotation":"720",
      "borderRadius":"50%",
      "backgroundColor":"#2fff00",
      "duration":"2"
   },
   "type":"from"
}

data-tl-tween-selector(可选)

和之前 tween 的 data-tween-selector 属性一样,在 timeline 里可以用 data-tl-tween-selector 属性把动画应用到自定义选择器:

也可以在 JSON 对象里通过 selector 属性覆盖这个值:

{
   "options":{
      "right":"0",
      "rotation":"720",
      "borderRadius":"50%",
      "backgroundColor":"#2fff00",
      "duration":"2"
   },
   "selector":".box2"
}

data-tl-tween-order(可选)

你可能会想显式设置每个 tween 在 timeline 里的顺序——比如先动画容器里最后一个 DOM 元素,再动画其他元素。这种情况下,直接在 data-tl-tween-order 属性里设置自定义顺序即可:

这个属性可选。留空的话,默认顺序值是 999

也可以在 JSON 对象里通过 order 属性覆盖这个值:

{
   "options":{
      "right":"0",
      "rotation":"720",
      "borderRadius":"50%",
      "backgroundColor":"#2fff00",
      "duration":"2"
   },
   "order":"1"
}

data-tl-tween-position(可选)

打造精美序列的秘诀是理解 position 参数——GSAP 的很多方法都会用到它。这个超灵活的参数控制 tween、标签、回调、暂停甚至嵌套 timeline 的摆放位置,所以你几乎可以把任何东西放到任何序列的任何位置。

官方文档

timeline 的默认行为是:tween B 在 tween A 播完后才开始。有些场景你想让 tween B 在 tween A 完成**之前(或之后)**开始。这时 data-tl-tween-position 属性就派上用场了。

比如我们想让某个 tween 在上一个 tween 播完 1 秒后再开始,就这样设置属性:

这个属性可选。默认值是 +=0。可以用的各种取值类型见官方文档

也可以在 JSON 对象里通过 position 属性覆盖这个值:

{
   "options":{
      "right":"0",
      "rotation":"720",
      "borderRadius":"50%",
      "backgroundColor":"#2fff00",
      "duration":"2"
   },
   "position":"+=1"
}

同一元素上的多个 tween

有时需要在 timeline 的不同位置给同一个元素加多个动画。用我们的 JavaScript Helper 完全没问题:在 data-tl-tween-options 属性里用 “;” 分隔多个 JSON 对象即可。

示例:

{
   "options":{
      "autoAlpha":"1"
   },
   "order":"0"
};{
   "options":{
      "autoAlpha":"0"
   },
   "order":"2"
};{
   "options":{
      "autoAlpha":"1"
   },
   "order":"4"
}

注意这不是合法的 JSON,因为 “;” 不是合法的分隔符。但别担心,脚本会先把这 3 个对象拆开,再逐个解析 JSON。

ScrollTrigger

ScrollTrigger 用极少的代码就能创建令人惊叹的滚动驱动动画。或者触发任何与滚动相关的东西,哪怕和动画完全无关。

官方文档

如果你按上面的步骤都做完了,你的 tween 和/或 timeline 已经设置好,页面加载后就能正常运行。

但如果你想等访客滚动到网站的特定区域再播放动画,而不是页面加载完就立刻播放呢?

用 GSAP 的 ScrollTrigger 插件 很容易做到。来看怎么做。

元素进入视口时触发动画

要在 tween 或 timeline 里激活 ScrollTrigger,只需在 JSON 选项文件里加几行。结构如下:

{
   "scrollTrigger":{
      "trigger":"#selector",
      "scrub":false,
   },
   ...your normal parameter...
}

用之前的例子演示一下:

{
   "scrollTrigger":{
      "trigger":"#container1",
      "scrub":false,
   },
   "right":"0",
   "rotation":"720",
   "borderRadius":"50%",
   "backgroundColor":"#2fff00",
   "duration":"2"
}

注意这一行:“trigger”:“#container1”。#container1 是触发元素的 ID——当它进入视口可见时,就会触发我们的动画。

这里我们用了 “scrub”:false:触发器激活后完整播放动画。后面我们看看 scrub 设为 true 时会发生什么。

理解视口的触发位置

定义滚动位置极其灵活——比如「该元素中心碰到视口中心时开始,那个元素底部碰到视口底部时结束」,可以用关键字(top、center、bottom、left、right)、百分比、像素,甚至相对值如 "+=300px"。掌握语法后,用起来非常直观。

官方文档

你可以根据元素在视口中的位置,轻松定义触发器何时激活。

比如想让触发元素的顶部碰到视口中心时激活动画,只需加一行代码:

{
   "scrollTrigger":{
      "trigger":"#selector",
      "scrub":false,
      "start":"top center"
   },
   ...your normal parameter...
}

如果想在网站上开启可视化标记(生产站不推荐),直观看到触发起止位置,就在 JSON 对象里加 “markers”:true

{
   "scrollTrigger":{
      "trigger":"#selector",
      "scrub":false,
      "start":"top center",
      "markers":true,
   },
   ...your normal parameter...
}

把动画绑定到鼠标滚动

ScrollTrigger 可以在进入/离开定义区域时对动画执行操作(play、pause、resume、restart、reverse、complete、reset),也可以直接把动画绑到滚动条上,让它像 scrubber 一样工作(scrub: true)。

官方文档

接下来是见证奇迹的时刻。你可能不想在触发器进入视口时一次性播完整个动画,而是想把动画和访客的鼠标滚动绑定起来。很简单:把 scrub 设为 true

{
   "scrollTrigger":{
      "trigger":"#selector",
      "scrub":true,
      "start":"top center"
   },
   ...your normal parameter...
}

你还可以软化动画和滚动条之间的绑定,让它花一定时间“追上”滚动——比如 scrub: 1 就是花 1 秒追上:

{
   "scrollTrigger":{
      "trigger":"#selector",
      "scrub":1,
      "start":"top center"
   },
   ...your normal parameter...
}

滚动时就会产生丝滑的联动效果。

最后的小贴士

不提到这个我没法收尾:Greensock 官方为所有 GSAP 相关动画制作了超好用的速查表:https://greensock.com/cheatsheet/。相信我,这是金子!

需要帮忙?

用 Bricks 建站?我接客户项目。

从快速营销站到完整的 Bricks 建站,再到从 Elementor 迁移——我都做过。本站每篇教程都来自真实项目经验。告诉我你的需求,一个工作日内回复。

  • Bricks 建站与改版
  • Elementor / Divi → Bricks 迁移
  • Bricks → Astro / headless 性能升级
  • 速度优化,PageSpeed 95+ 目标