革命性创新,动画杀手锏 @scroll-timeline
在 CSS 规范 Scroll-linked Animations 中,推出了一个划时代的 CSS 功能。也就是 -- The @scroll-timeline at-rule,直译过来就是滚动时间线。
本文,就将带大家一探究竟,从入门到学会使用 CSS @scroll-timeline
。
何为 @scroll-timeline 滚动时间线?
什么是 @scroll-timeline
滚动时间线呢?
@scroll-timeline
能够设定一个动画的开始和结束由滚动容器内的滚动进度决定,而不是由时间决定。
意思是,我们可以定义一个动画效果,该动画的开始和结束可以通过容器的滚动来进行控制。
示意 DEMO
再系统性学习语法之前,我们通过一个 DEMO,简单了解一下它的用法:
我们首先实现一个简单的字体 F 旋转动画:
<div id="g-box">F</div>
#g-box {
animation-name: rotate;
animation-duration: 3s;
animation-direction: alternate;
animation-easing-function: linear;
}
@keyframes rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
正常而言,它是这样一个简单的动画:
接下来,我们把这个动画和 @scroll-timeline
相结合,需要把它放置到一个可滚动的容器中:
<div id="g-content">
<div id="g-box">F</div>
</div>
#g-content {
width: 300px;
height: 170vh;
background: #999;
}
#g-box {
font-size: 150px;
margin: 70vh auto 0;
animation-name: rotate;
animation-duration: 3s;
animation-direction: alternate;
animation-easing-function: linear;
animation-timeline: box-rotate;
}
@keyframes rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
@scroll-timeline box-rotate {
source: selector("#g-content");
}
这里,我们实现了一个可滚动容器 #g-content
,它的高度是 170vh
,也就是可视界面高度的 1.7 倍,并且把 #g-box
容器放置在一个距离顶部 70vh
高度的地方:
有意思的来了,我们设置的旋转动画不会自动开始,只有当我们向下滚动的时候,动画才会开始进行,实际效果 Gif:
CodePen Demo -- @scroll-timeline Demo
看到这里,大家应该能够理解 @scroll-timeline
的作用及含义了,它赋予了 CSS 能够基于滚动条的滚动去控制动画行进的能力! Amazing!!
@scroll-timeline 语法介绍
接下来,我们先缓一缓,简单看一看 @scroll-timeline
的语法。
使用 @scroll-timeline
,最核心的就是需要定义一个 @scroll-timeline
规则:
@scroll-timeline moveTimeline {
source: selector("#g-content");
orientation: vertical;
scroll-offsets: 0px, 500px;
}
其中:
- source:绑定触发滚动动画的滚动容器
source: auto
:绑定到Document
,也就是全局 Windows 对象source: selector("id-selector")
,通过selector()
,内置一个#id
选择器,选取一个可滚动容器source: none
:不指的滚动容器
- orientation:设定滚动时间线的方向
orientation: auto
:默认为 vertical,也就是竖直方向的滚动orientation: vertical
:竖直方向的滚动orientation: horizontal
:水平方向的滚动orientation: block
:不太常用,使用沿块轴的滚动位置,符合书写模式和方向性orientation: inline
:不太常用,使用沿内联轴的滚动位置,符合书写模式和方向性
- scroll-offsets:滚动时间线的核心,设定在滚动的什么阶段,触发动画,可通过三种方式之一进行设置:
scroll-offsets: none
这意味着没有 scroll-offset 指定。- 由逗号分隔的 length-percentage 值列表确定。每个值都映射到animation-duration。例如,如果 ananimation-duration 设置为 2s 且滚动偏移量为 0px, 30px, 100px,则在 1s 时,滚动偏移量将为 30px。
- 第三种确定滚动偏移量的方法是使用元素偏移量。这意味着可以指定页面内的元素,其位置决定了滚动时间线以及要使用这些元素的哪个边缘。指定元素是使用 selector() 函数完成的,该函数接收元素的 id。边缘由关键字 start 或确定 end。可选的阈值的 0–1 可用于表示元素滚动中预期可见的百分比。
scroll-offsets
的理解会比较困难,我们稍后详述。
在设定了一个 @scroll-timeline
之后,我们只需要将它和动画绑定起来即可,通过 animation-timeline
:
@scroll-timeline moveTimeline {
source: selector("#g-content");
orientation: vertical;
scroll-offsets: 0px, 500px;
}
div {
animation-name: move;
animation-duration: 3s;
animation-timeline: moveTimeline;
}
@keyframes move{
0% {
transform: translate(0, 0);
}
100% {
transform: translate(100%, 0);
}
}
使用 @scroll-timeline 实现滚动进度指示器
之前在 不可思议的纯 CSS 滚动进度条效果 一文中,我们介绍了一种使用渐变实现的纯 CSS 滚动进度指示器效果:
该方法有些小小的瑕疵。其中一个就是当滚动距离太短的时候,进度条右侧会有明显的斜边效果。
而有了 @scroll-timeline
之后,我们终于可以将滚动和动画这两个元素绑定起来,再实现滚动进度指示器,就已经非常轻松了:
<div id="g-container">
<p>...文本内容...</p>
</div>
#g-container {
width: 100vw;
}
#g-container::before {
content: "";
position: fixed;
height: 5px;
left: 0;
top: 0;
right: 0;
background: #ffc107;
animation-name: scale;
animation-duration: 1s;
animation-fill-mode: forwards;
animation-timeline: box-rotate;
transform-origin: 0 50%;
}
@keyframes scale {
0% {
transform: scaleX(0);
}
100% {
transform: scaleX(1);
}
}
@scroll-timeline box-rotate {
source: auto;
orientation: vertical;
}
- 我们在页面最上方,通过一个伪元素,实现一个占满屏幕
100%
的5px
高的进度条。正常而言是这样:
- 通过设定一个
transform: scaleX(0)
到transform: scaleX(1)
的动画,并且将它与 body 的滚动相绑定,即可得到滚动指示器,效果如下:
完整的代码,你可以戳这里:CodePen Demo - 使用 @scroll-timeline 实现滚动进度条
使用 scroll-offsets 精确控制动画触发时机
大家可以再看看上面的 Gif 图,都有一个问题,就是动画的开始时间都是从滚动一开始就开始了,刚好在滚动结束时结束。那么如果我希望动画在滚动的特定阶段触发,那该怎么办呢?
这里,就需要借助 scroll-offsets
,去更加精确的控制我们的动画。
在滚动过程中,我们可以将一个元素,划分为 3 个区域:
- 滚动过程中,从上方视野盲区,进入视野
- 滚动过程中,处于视野中
- 滚动过程中,从视野中,进入下方视野盲区
在这里,我们就可以得到两个边界,上方边界,下方边界:
而对于上下两个边界,又会有两种状态。以上边界为例子,会有:
- 元素刚刚开始进入可视区
- 元素完全进入可视区
对于这两种状态,我们用 start 0
和 start 1
表示,同理,下方的边界也可以用 end 0
和 end 1
表示:
这里的 0 和 1 实际表示的是,元素滚动中预期可见的百分比。
有了这些状态值,配合 scroll-offsets
,我们就可以精确控制滚动动画的触发时间。
我们设定一个从左向右并且伴随透明度变化的动画,的看看下面几种情况:
- 滚动动画在元素从下方开始出现时开始,完全出现后截止。
动画运行范围:end 0
--> end 1
:
@keyframes move {
0% {
transform: translate(-100%, 0);
opacity: 0;
}
100% {
transform: translate(0, 0);
opacity: 1;
}
}
@scroll-timeline box-move {
source: auto;
orientation: "vertical";
scroll-offsets:
selector(#g-box) end 0,
selector(#g-box) end 1;
/* Legacy Descriptors Below: */
start: selector(#g-box) end 0;
end: selector(#g-box) end 1;
time-range: 1s;
}
#g-box {
animation-name: move;
animation-duration: 3s;
animation-fill-mode: both;
animation-timeline: box-move;
}
效果如下:
- 滚动动画在元素从下方完全出现时开始,在滚动到上方即将离开屏幕后截止:
动画运行范围:end 1
--> start 1
:
// ...
@scroll-timeline box-move {
source: auto;
orientation: "vertical";
scroll-offsets:
selector(#g-box) end 1,
selector(#g-box) start 1;
/* Legacy Descriptors Below: */
start: selector(#g-box) end 1;
end: selector(#g-box) start 1;
time-range: 1s;
}
// ...
效果如下:
- 滚动动画在元素滚动到上方即将离开屏幕后开始,完全离开屏幕后截止:
动画运行范围:start 1
--> start 0
:
// ...
@scroll-timeline box-move {
source: auto;
orientation: "vertical";
scroll-offsets:
selector(#g-box) start 1,
selector(#g-box) start 0;
/* Legacy Descriptors Below: */
start: selector(#g-box) start 1;
end: selector(#g-box) start 0;
time-range: 1s;
}
// ...
效果如下:
掌握 scroll-offsets
的用法是灵活运用滚动时间线的关键,当然,在上面你还会看到 start: selector(#g-box) start 1
和 end: selector(#g-box) start 0
这种写法,这是规范历史遗留问题,最新的规范已经使用了 scroll-offsets
去替代 start:
和 end:
的写法。
把上述 3 种情况放在一起,再比较比较:
完整的代码,你可以戳这里:CodePen Demo - @scroll-timeline Demo | element-based offset
使用 @scroll-timeline 实现各类效果
在能够掌握 @scroll-timeline 的各个语法之后,我们就可以开始使用它创造各种动画效果了。
譬如如下的,滚动内容不断划入:
代码较长,可以戳这里,来自 bramus 的 Codepen CodePen Demo -- Fly-in Contact List (CSS @scroll-timeline version)
甚至可以结合 scroll-snap-type
制作一些全屏滚动的大屏特效动画:
要知道,这在以前,是完全不可能利用纯 CSS 实现的。完整的代码你可以戳这里:CodePen Demo -- CSS Scroll-Timeline Split Screen Carousel
简而言之,任何动画效果,如今,都可以和滚动相结合起来,甚至乎是配合 SVG 元素也不例外,这里我还简单改造了一下之前的一个 SVG 线条动画:
完整的代码你可以戳这里:CodePen Demo -- SVG Text Line Effect | Scroll Timeline
@scroll-timeline 的实验室特性与特性检测
@scroll-timeline
虽好,目前仍处于实验室特性时间,Chrome 从 85 版本开始支持,但是默认是关闭的。
兼容性如下(2022-03-07):
在最新的 chrome、Edge、Opera 可以通过浏览器配置开启该特性,Chrome 下开启该特性需要:
- 浏览器 URL 框输入
chrome://flags
- 开启
#enable-experimental-web-platform-features
美酒虽好,但是离完全能用,浏览器大规模支持还需要等待一会,给时间一点时间吧!
特性检测
基于目前的兼容性问题,我们可以通过浏览器的特性检测 @supports
语法,来渐进增强使用该功能。
特性检测的语法也非常简单:
@supports (animation-timeline: works) {
@scroll-timeline list-item-1 {
source: selector(#list-view);
start: selector(#list-item-1) end 0;
end: selector(#list-item-1) end 1;
scroll-offsets:
selector(#list-item-1) end 0,
selector(#list-item-1) end 1
;
time-range: 1s;
}
// ...
}
通过 @supports (animation-timeline: works) {}
可以判断浏览器是否支持 @scroll-timeline
。
最后
目前关于 @scroll-timeline 的相关介绍还非常少,但是它确是能够改变 CSS 动画的一个非常大的革新。随着兼容性的逐渐普及,未来势必会在 CSS 中占据一席之地。
本文到此结束,希望对你有帮助
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
革命性创新,动画杀手锏 @scroll-timeline的更多相关文章
- javaScript动画2 scroll家族
offsetWidth和offsetHight (检测盒子自身宽高+padding+border) 这两个属性,他们绑定在了所有的节点元素上.获取之后,只要调用这两个属性,我们就能够获取元素节点的宽和 ...
- Unity中的动画系统和Timeline(5) Timeline
在前面的动画,都是控制单独的物体,比如说控制一个角色的运动.而Timeline,可以对多个物体实施动画,形成过场动画,或者电影效果.比如,很多赛车游戏比赛开始前都会播放一段开场动画,围绕自己车的几个方 ...
- Unity中的动画系统和Timeline(2) 按钮动画和2D精灵动画
按钮动画 1 创建按钮后,按钮的Button组件中,Transition我们平时用的时Tint,这次选择Animation 选择Auto Generate Animation,创建一个按钮动画 2 后 ...
- Unity中的动画系统和Timeline(1) 普通动画创建
学习使用版本:Unity2017.1.1 目标:给一个Cube创建动画 一:第一种创建方法 1 Windows —— Animation,打开Aniamtion动画界面,此时显示 因为此时没有任何动画 ...
- Unity中的动画系统和Timeline(3) 模型和动画导入
动画导入 美工做好的模型,直接将文件夹拖进来就导入好了.导入模型后,检查模型的材质贴图等是否丢失,若丢失,根据名字补上.如果美工取名规范,一一对应的话,就很简单.如果不是,那就呵呵哒. 有的美工做的比 ...
- Unity中的动画系统和Timeline(4) AvatarMask和IK动画
AvatarMask(骨骼遮罩) 在前面角色动画的基础上,角色在奔跑过程中捡起一块木头,双手要抱着这块木头.如果使用前面的方法,直接切换动画,那么就只剩下抱木头的动画,其它动画就没了.这时我们要使用下 ...
- Unity中的动画系统和Timeline(3) 混合树和动画匹配
混合树 前面我们通过在Animation界面添加单独的动作来控制动画,这样做比较麻烦,每个单独的属性,比如站立,奔跑等,都需要单独的代码来控制.现在我们可以通过使用混合树,其基本思想是将相近的动画混合 ...
- 1.关于QT中的Graphics绘图,定时器,动画,将窗口中的内容打印到图片上,打印机,打印预览
1 新建项目 A 修改pro中的内容如下: HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets prints ...
- Timeline高级扩展
转载于http://forum.china.unity3d.com/thread-32200-1-1.html通过demo讲解了timeline更加复杂的使用方式 Timeline是创建过场动画和影片 ...
随机推荐
- JVM专题1: 类和类加载机制
合集目录 JVM专题1: 类和类加载机制 Java对象的结构 在HotSpot虚拟机中, 对象在内存中存储的布局可以分为3块区域 对象头Header 实例数据Instance Data 对齐填充Pad ...
- nohub命令简单介绍。
/* 来自对 https://www.cnblogs.com/kexianting/p/11628983.html 编辑. 一 什么是 nohub? 1 是 no hang up 的缩写,就是不挂断的 ...
- JDBC 连接DRUID 连接池!
一.1.创建一个floder目录,[名称lib] 2. 导入mysql.jar包和 druid.jar 包.---------->bulid path 二.创建 sourcefolder 目录 ...
- css自定义属性(css变量)
感谢原文作者:Kuku殿下 原文链接:https://segmentfault.com/a/1190000015948538 前言 刚开始的"css变量",经扩展之后,称为&quo ...
- JavaWeb编码浅解
感谢原文作者:少年无形 原文链接:https://blog.csdn.net/dl18215164175/article/details/72512131?depth_1-utm_source=dis ...
- linux内核中的eventfd
转载请注明来源:https://www.cnblogs.com/hookjc/ eventfd 在内核版本,2.6.22以后有效.查看内核版本可以用命令 uname -r . [cpp] view p ...
- 第11、12章等待方法和alter框处理
11.等待方法 time sleep webdriver implicitly_wait() 设置浏览器等待时间 WebDriverWait 等待条件满足或超时后退出 12.alter对话框处理 ...
- 基于GDAL库,读取.grd文件(以海洋地形数据为例)Java版
技术背景 海洋地形数据主要是通过美国全球地形起伏数据(GMT)获得,数据格式为grd(GSBG)二进制数据,打开软件通过是Surfer软件,surfer软件可进行数据的编辑处理,以及进一步的可视化表达 ...
- Solution -「CF 1025G」Company Acquisitions
\(\mathcal{Description}\) Link. \(n\) 个公司,每个公司可能独立或者附属于另一个公司.初始时,每个公司附属于 \(a_i\)(\(a_i=-1\) 表示该公 ...
- Spring系列15:Environment抽象
本文内容 Environment抽象的2个重要概念 @Profile 的使用 @PropertySource 的使用 Environment抽象的2个重要概念 Environment 接口表示当前应用 ...