革命性创新,动画杀手锏 @scroll-timeline

简介: 革命性创新,动画杀手锏 @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);
    }
}


正常而言,它是这样一个简单的动画:


c8f35d8ffac04d3581a8bfbfc6ba2116_tplv-k3u1fbpfcp-zoom-1.gif

接下来,我们把这个动画和 @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 高度的地方:


89276b4887724ed0aea7035f9e04aa57_tplv-k3u1fbpfcp-zoom-1.png


有意思的来了,我们设置的旋转动画不会自动开始,只有当我们向下滚动的时候,动画才会开始进行,实际效果 Gif:


9ae0d7a408b54dfc88fa337e49b7ba2a_tplv-k3u1fbpfcp-zoom-1.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 滚动进度指示器效果:


338b335bb3ad44748f6b1f74847812cc_tplv-k3u1fbpfcp-zoom-1.gif


该方法有些小小的瑕疵。其中一个就是当滚动距离太短的时候,进度条右侧会有明显的斜边效果。


而有了 @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;
}


  1. 我们在页面最上方,通过一个伪元素,实现一个占满屏幕 100% 的 5px 高的进度条。正常而言是这样:


c0f0a37510084e7c8ce9412b0f1a3a76_tplv-k3u1fbpfcp-zoom-1.png

通过设定一个 transform: scaleX(0) 到 transform: scaleX(1) 的动画,并且将它与 body 的滚动相绑定,即可得到滚动指示器,效果如下:

image.png


完整的代码,你可以戳这里:CodePen Demo - 使用 @scroll-timeline 实现滚动进度条


使用 scroll-offsets 精确控制动画触发时机



大家可以再看看上面的 Gif 图,都有一个问题,就是动画的开始时间都是从滚动一开始就开始了,刚好在滚动结束时结束。那么如果我希望动画在滚动的特定阶段触发,那该怎么办呢?


这里,就需要借助 scroll-offsets,去更加精确的控制我们的动画。


在滚动过程中,我们可以将一个元素,划分为 3 个区域:


  • 滚动过程中,从上方视野盲区,进入视野
  • 滚动过程中,处于视野中
  • 滚动过程中,从视野中,进入下方视野盲区


在这里,我们就可以得到两个边界,上方边界,下方边界:

20fba7cafed24a908d7a237623e339f7_tplv-k3u1fbpfcp-watermark.png


而对于上下两个边界,又会有两种状态。以上边界为例子,会有:


  • 元素刚刚开始进入可视区
  • 元素完全进入可视区


对于这两种状态,我们用 start 0 和 start 1 表示,同理,下方的边界也可以用 end 0 和 end 1表示:


5ab409994ddf4d4b8505abc6e347c9dd_tplv-k3u1fbpfcp-zoom-1.png



这里的 0 和 1 实际表示的是,元素滚动中预期可见的百分比。


有了这些状态值,配合 scroll-offsets,我们就可以精确控制滚动动画的触发时间。

我们设定一个从左向右并且伴随透明度变化的动画,的看看下面几种情况:

  1. 滚动动画在元素从下方开始出现时开始,完全出现后截止。


动画运行范围: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;
}


效果如下:


9218315042d14ad889cb55e28513d334_tplv-k3u1fbpfcp-zoom-1.gif



  1. 滚动动画在元素从下方完全出现时开始,在滚动到上方即将离开屏幕后截止:

动画运行范围: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;
}
// ...


效果如下:

95dcbc85475d49fab987676d048a781e_tplv-k3u1fbpfcp-zoom-1.gif



  1. 滚动动画在元素滚动到上方即将离开屏幕后开始,完全离开屏幕后截止:

动画运行范围: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;
}
// ...


效果如下:


33bdc1c02f964fc29fd8349604071bd8_tplv-k3u1fbpfcp-zoom-1.gif


掌握 scroll-offsets 的用法是灵活运用滚动时间线的关键,当然,在上面你还会看到 start: selector(#g-box) start 1 和 end: selector(#g-box) start 0 这种写法,这是规范历史遗留问题,最新的规范已经使用了 scroll-offsets 去替代 start: 和 end: 的写法。

把上述 3 种情况放在一起,再比较比较:


2dc1f2974565463b840d3542c7e4554d_tplv-k3u1fbpfcp-watermark.gif


完整的代码,你可以戳这里:CodePen Demo - @scroll-timeline Demo | element-based offset


使用 @scroll-timeline 实现各类效果



在能够掌握 @scroll-timeline 的各个语法之后,我们就可以开始使用它创造各种动画效果了。

譬如如下的,滚动内容不断划入:

e787256333d146198092c242f6d89095_tplv-k3u1fbpfcp-zoom-1.gif


代码较长,可以戳这里,来自 bramus 的 Codepen CodePen Demo -- Fly-in Contact List (CSS @scroll-timeline version)


甚至可以结合 scroll-snap-type 制作一些全屏滚动的大屏特效动画:

41823844352d41f1ae763ad5f680307e_tplv-k3u1fbpfcp-watermark.gif


要知道,这在以前,是完全不可能利用纯 CSS 实现的。完整的代码你可以戳这里:CodePen Demo -- CSS Scroll-Timeline Split Screen Carousel


简而言之,任何动画效果,如今,都可以和滚动相结合起来,甚至乎是配合 SVG 元素也不例外,这里我还简单改造了一下之前的一个 SVG 线条动画:


51cf0af970e14b1b975535763fe35d95_tplv-k3u1fbpfcp-zoom-1.gif


完整的代码你可以戳这里:CodePen Demo -- SVG Text Line Effect | Scroll Timeline


@scroll-timeline 的实验室特性与特性检测



@scroll-timeline 虽好,目前仍处于实验室特性时间,Chrome 从 85 版本开始支持,但是默认是关闭的。


兼容性如下(2022-03-07):


e52a88d560124f1e88cd8189f0cd1e2b_tplv-k3u1fbpfcp-zoom-1.png

在最新的 chrome、Edge、Opera 可以通过浏览器配置开启该特性,Chrome 下开启该特性需要:


  1. 浏览器 URL 框输入 chrome://flags
  2. 开启 #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

目录
相关文章
|
6月前
|
前端开发 开发者 UED
解锁网页布局的秘密武器:探索 CSS Grid 布局的神奇魔力
解锁网页布局的秘密武器:探索 CSS Grid 布局的神奇魔力
53 3
|
2月前
|
前端开发 开发者 容器
【布局革命!】Flexbox与Grid双剑合璧:解锁Web设计新纪元,让响应式界面瞬间焕发光彩!
【9月更文挑战第1天】本文通过问答形式深入探讨了Flexbox和Grid布局的特点与应用场景。Flexbox专为单轴布局设计,适用于响应式导航栏和列表;Grid布局则适用于二维布局,可精确控制元素的位置和大小,适合构建复杂的内容区域和仪表板。文章还提供了示例代码,帮助读者更好地理解和应用这两种布局方式,以创建高效、美观的Web界面。
81 9
|
3月前
|
C# UED 开发者
WPF与性能优化:掌握这些核心技巧,让你的应用从卡顿到丝滑,彻底告别延迟,实现响应速度质的飞跃——从布局到动画全面剖析与实例演示
【8月更文挑战第31天】本文通过对比优化前后的方法,详细探讨了提升WPF应用响应速度的策略。文章首先分析了常见的性能瓶颈,如复杂的XAML布局、耗时的事件处理、不当的数据绑定及繁重的动画效果。接着,通过具体示例展示了如何简化XAML结构、使用后台线程处理事件、调整数据绑定设置以及利用DirectX优化动画,从而有效提升应用性能。通过这些优化措施,WPF应用将更加流畅,用户体验也将得到显著改善。
220 1
|
3月前
|
前端开发 UED
超越静态:CSS动画轮播图,引领视觉新体验!
超越静态:CSS动画轮播图,引领视觉新体验!
|
3月前
|
前端开发
视觉充电:CSS动画特效,为网站带来动力与活力!(一键复制)
视觉充电:CSS动画特效,为网站带来动力与活力!(一键复制)
|
图形学
Unity Metaverse(二)、Mixamo & Animator 混合树与动画融合
Blend Tree混合树的使用与动画融合的实现
308 1
Unity Metaverse(二)、Mixamo & Animator 混合树与动画融合
3D 动画解决方案
本文研究全球及中国市场3D 动画解决方案现状及未来发展趋势,侧重分析全球及中国市场的主要企业,同时对比北美、欧洲、中国、日本、东南亚和印度等地区的现状及未来发展趋势
|
Web App开发 JSON 测试技术
更强的动画能力,更好的渲染质感,Oasis Engine 0.5 发布
本次里程碑重点重新设计了动画系统,提供了全新的 Animator 组件并支持了 BlendShape 动画,动画能力得到大幅提升。渲染方面重新设计了 PBR 材质接口,环境光的漫反射部分提供了球谐模式,PBR 工作流得到提升。2D 方面增加了精灵图集功能,Spine 增强了换肤能力,Lottie 动画也集成到编辑器中。官网支持中英文双语,新增 20+ 示例。
更强的动画能力,更好的渲染质感,Oasis Engine 0.5 发布
|
云安全 敏捷开发 监控
成功过渡到云需要重塑IT
为了能够成功过渡到云,首席信息官们正在重新组建他们的IT团队,使其变得敏捷、跨职能,并且拥有新的技能、角色和高度适应性的思维方式。
119 0
如何把握好 transition 和 animation 的时序,创作描边按钮特效
效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。 https://codepen.io/comehope/pen/mKdzZM 可交互视频教程 此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。
930 0