受苹果网页动画的启发,我写了一个JS库
大家好,我是 Steven。
我喜欢苹果的产品,也喜欢他们的网站。他们在网页中做了很多很棒的动画效果来介绍产品,大部分都是基于页面滚动的,当我们上下滚动网页时,动画会向前和向后播放。
作为一名前端开发者,我常常试着重现他们的动画来学习,并将其录制为教学视频。
而要实现基于页面滚动的动画,必须使用 JavaScript 做一些计算,比如元素是否出现在屏幕上、滚动的距离、元素偏移量等等,然后相应地更新元素的样式。
由于实现这类动画都有着以上提到的共通点,我在想能否把开发过程变得更简单,比如说,不用编写一行 JavaScript 就可以实现这类动画。
初始想法
基于页面滚动的动画效果,主要关乎到滚动的距离以及元素的位置。元素从页面底部出现到从顶部消失,我希望通过一个数字来表达,从 0
到 1
就很适合,至少就目前来说。
然后使用 IntersectionObserver
API 来监听元素是否出现在屏幕当中。接下来,就要考虑用什么方式来使用这个数字。
灵活性
由于动画千变万化,例如元素的淡入淡出、元素的移动、改变文本的颜色等等,而且不仅于此。所以我们需要一个足够灵活的方式来调整样式,CSS 变量就是一个很好的选择。
库的名称
我将这个库命名为 Trigger JS,Trigger 的意思是触发。因为每次滚动都会触发一个新的值,纯碎是字面意思。
对 JavaScript 使用的思考
这个库的目标是让开发者在无需编写 JavaScript 的情况下,即可建立基于页面滚动的动画。所以,我决定通过 HTML 属性和 CSS 变量来实现。
由于库名是 Trigger JS,所以我使用了 tg-
作为相关 HTML 属性的前缀。我知道 tg-
可能不太符合 HTML5 的标准,没关系,我会保留一个选项来自定义前缀,例如data-tg-*
,彻底摆脱这个顾虑。而本文将继续使用 tg-
来讲解。
第一个属性:tg-name
tg-name
属性主要有两个用途:定义需要监控的元素和 CSS 变量的名称。
将 tg-name
属性添加到需要监控的元素中,例如:
<h1 tg-name="opacity"> Hello World </h1> 复制代码
Trigger JS 会将所有带有 tg-name
属性的 HTML 元素获取到一个名为 activeElements
的数组中(通过 document.querySelector('[tg-name'])
),并使用 IntersectionObserver
API 来监听它们的出现。
增加一个 scroll
事件监听器到 window
,计算 activeElements
中元素相对与屏幕的位置:元素从底部出现时为 0
,从顶部消失时为 1
,在中间时为 0.5
。
最后,我们将这个计算结果通过 CSS 变量设定到指定的元素中,例如 --opacity: 0.5
。这样我们就可以在相应的 CSS 属性中应用该值,在本例中,就是 opacity: var(--opacity);
。
设置数值范围
从 0
到 1
这个数字,在某些情况下很好。但是如果我们想通过 transform
来移动一个元素,调整数值的起始和结束值就会变得更为方便(尽管可以在 CSS 中通过 calc()
来计算)。
这就是为什么我添加了 tg-from
和 tg-to
。如果想在页面向上滚动时,将元素由右往左移动 400px
,可以设置 tg-from="200"
和 tg-to="-200"
。
对了,还需要定义间距,设置为 tg-steps="400"
就等于每次移动 1px
。但是如果我们更改了 tg-from
和 tg-to
,又想保持每一次递增 1px
的话,可以使用另一个属性 tg-step="1"
,这样就不用自行计算了。
数字并不完美
有时,我们需要一个特定的值。假设我们要更改文本颜色,需要的是颜色代码而不是数字。这就是添加 tg-map
属性的原因,使我们能够将值从数字转换为特定的值。
例如:
<h1 tg-name="color" tg-from="0" tg-to="2" tg-step="1" tg-map="0: black; 1: blue; 2: purple" > Hello World <h1> 复制代码
在整个滚动过程中,计算值将是 0
、1
或 2
。然后使用 tg-map
中的设置转换为最终值:
0
->black
1
->blue
2
->purple
因此,我们可以使用以下方式轻松更新文本颜色:
<style> h1 { color: var(--color); } </style> 复制代码
降噪
有时我们只对某些特定的值感兴趣。例如,我们只想知道从 0
至 100
(tg-from="0"
以及 tg-to="100"
) 之间,什么时候出现 25
, 50
, 75
。在这个情况中,tg-filter
就可以帮上忙。
<h1 id="heading" tg-name="color" tg-from="0" tg-to="100" tg-step="1" tg-filter="25,50,75" tg-map="25: red; 50: yellow; 75: green" > Red (25), Yellow (50), Green (75) </h1> <style> body { padding: 100vh 0; /* In order to make the page have enough rooms for scrolling */ } #heading { color: var(--color); } </style> 复制代码
开源
以上是创建这个 JS 库的原因以及想法,目前 Trigger JS 已开源,可以在 GitHub-triggerjs/trigger 找到。
欢迎您测试它,提交 PR 请求并分享您的想法,您的意见对于 Trigger JS 的发展非常宝贵。
如果您喜欢它,请给它一个 Star。如果能有您的参与就更好了!
作者:CodingStartup起码课
链接:https://juejin.cn/post/7023662755668295711