【动画进阶】当路径动画遇到滚动驱动!

这篇具有很好参考价值的文章主要介绍了【动画进阶】当路径动画遇到滚动驱动!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我的小册 《CSS 技术揭秘与实战通关》上线了,想了解更多有趣、进阶、系统化的 CSS 内容,可以猛击 - LINK。

本文,我们将一起利用纯 CSS,实现如下这么个酷炫的效果:

【动画进阶】当路径动画遇到滚动驱动!

在一年前,我介绍了 CSS 中非常新奇有趣的一个新特性 -- @scroll-timeline:革命性创新,动画杀手锏 @scroll-timeline。

利用这个新特性,我们可以轻松的将原本基于时间控制的动画效果,交给页面的滚动特性进行控制,像是这样:

【动画进阶】当路径动画遇到滚动驱动!

只是,该特性由于诸多原因,遭到了规范废弃。

然而,时隔一年半,规范带着新的 animation-timeline 王者回归!我们可以将其简单理解为:Scroll-driven Animations(滚动驱动动画)

什么是滚动驱动动画(Scroll-driven Animations)?

OK,我们通过一个例子,快速上手(回忆)滚动驱动动画。

我们来实现这么一个滚动进度指示器效果:

【动画进阶】当路径动画遇到滚动驱动!

注意看 GIF 图的上方,有一个黄色进度条,可以通过滚动,改变黄色进度条的进度状态。这个也就是我们说的滚动指示器效果。

在之前,这个效果利用纯 CSS 是不太好实现的,但是有了 animation-timeline 之后,一切都将变得非常轻松。

假设我们有如下结构:

<div id="g-container">
    <h1>不可思议的纯 CSS 进度条效果</h1>
    <p>OK,继续....../p>
    // ...
</div>
body {
    overflow: scroll;
}
#g-container {
    width: 100vw;
}

其中,#g-container 有非常多的内容,其长度远远超过 100vh,也就是一个屏幕的高度。并且,body 是设置了 overflow: scroll 的。因此,整个页面是可以进行滚动的:

【动画进阶】当路径动画遇到滚动驱动!

好,接下来,我们需要加上进度条,实现的方式有非常多种,这里我通过给 #g-container 添加一个伪元素,将进度条的效果设置给这个伪元素,代码也非常简单:

#g-container::before {
    content: "";
    position: fixed;
    height: 7px;
    left: 0;
    top: 0;
    right: 0;
    background: #ffc107;
    animation: scale 3s linear infinite;
    transform-origin: 0 50%;
}

@keyframes scale {
    0% {
        transform: scaleX(0);
    }
    100% {
        transform: scaleX(1);
    }
}

这里,利用元素的缩放,从 transform: scaleX(0)transform: scaleX(1) 的变化,实现了进度条的动画效果。

只不过,目前是一个无限动画,一次动画效果持续 3 秒 -- animation: scale 3s linear infinite

【动画进阶】当路径动画遇到滚动驱动!

好,铺垫到这里,接下来终于要轮到 animation-timeline 登场了。

上述的动画效果,目前是由时间进行控制的,持续时长为 3s,而我们的目标,就是利用滚动的效果控制整个动画。

我们只需要简单的改造一下代码:

#g-container::before {
    // ...
    animation: scale 3s linear;
    animation-timeline: scroll(root);
    transform-origin: 0 50%;
}

这里,我们仅仅加了一句 animation-timeline: scroll(root),表示利用滚动进行元素的动画控制,并且利用的是 root 元素的滚动,也就是 body 元素的滚动进行控制。

这样,我们就轻松的实现了一个滚动指示器效果:

【动画进阶】当路径动画遇到滚动驱动!

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

当然,整个滚动驱动动画(Scroll-driven Animations)的内容还是非常多的,本文不对基础语法做过多展开,大家可以通过下面两个途径,进一步了解新语法:

  1. MDN 文档 -- animation-timeline
  2. XboxYan 大佬的 CSS 滚动驱动动画终于正式支持了~

借用 XboxYan 文章中的一幅图:

【动画进阶】当路径动画遇到滚动驱动!

motion-path 运动路径动画

好,到目前位置,我们都还在铺垫内容,本文的核心是当路径动画遇到滚动驱动

那么,了解完滚动驱动动画之后,我们再来了解一下,什么是运动路径动画 -- motion-path

motion-path 在之前,也有过系统的介绍 -- 探秘神奇的运动路径动画 Motion Path

什么是 CSS Motion Path 运动路径?利用这个规范规定的属性,我们可以控制元素按照特定的路径进行位置变换的动画。并且,这个路径可以是非常复杂的一条路径。

初窥 motion-path

CSS Motion Path 规范主要包含以下几个属性:

  • offset-path:接收一个 SVG 路径(与 SVG 的path、CSS 中的 clip-path 类似),指定运动的几何路径
  • offset-distance:控制当前元素基于 offset-path 运动的距离
  • offset-position:指定 offset-path 的初始位置
  • offset-anchor:定义沿 offset-path 定位的元素的锚点。 这个也算好理解,运动的元素可能不是一个点,那么就需要指定元素中的哪个点附着在路径上进行运动
  • offset-rotate:定义沿 offset-path 定位时元素的方向,说人话就是运动过程中元素的角度朝向

下面,我们使用 Motion Path 实现一个简单的直线位移动画。

<div>
div {
    width: 60px;
    height: 60px;
    background: linear-gradient(#fc0, #f0c);
    offset-path: path("M 0 0 L 100 100");
    offset-rotate: 0deg;
    animation: move 2000ms infinite alternate ease-in-out;
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}

offset-path 接收一个 SVG 的 path 路径,这里我们的路径内容是一条自定义路径 path("M 0 0 L 100 100"),翻译过来就是从 0 0 点运动到 100px 100px 点。

offset-path 接收一个 SVG 路径,指定运动的几何路径。与 SVG 的path、CSS 中的 clip-path 类似,对于这个 SVG Path 还不太了解的可以戳这里先了解下 SVG 路径内容:SVG 路径

我们会得到如下结果:

【动画进阶】当路径动画遇到滚动驱动!

通过控制元素的 offset-distance0% 变化到 100% 进行元素的路径动画。

当然,上述的动画是最基本的,我可以充分利用 path 的特性,增加多个中间关键帧,稍微改造下上述代码:

div {
    // 只改变运动路径,其他保持一致
    offset-path: path("M 0 0 L 100 0 L 200 0 L 300 100 L 400 0 L 500 100 L 600 0 L 700 100 L 800 0");
    animation: move 2000ms infinite alternate linear;
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}

这里最主要还是运用了 path 中的 L 指令,得到了如下图这样一条直线路径:

【动画进阶】当路径动画遇到滚动驱动!

最终的效果如下,与利用 transform: translate() 添加多个关键帧类似:

【动画进阶】当路径动画遇到滚动驱动!

完整的 Demo 你可以戳这里:CodePen Demo -- CSS Motion Path Demo

曲线路径动画

上面的运动轨迹都是由直线构成,下面我们看看如何使用 CSS Motion Path 实现曲线路径动画。

其实原理还是一模一样,只需要在 offset-path: path() 中添加曲线相关的路径即可。

在 SVG 的 Path 中,我们取其中一种绘制曲线的方法 -- 贝塞尔曲线,譬如下述这条 path,其中的 path 为 d="M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80"

<svg width="400" height="160" xmlns="http://www.w3.org/2000/svg">
  <path d="M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80" stroke="black" fill="transparent"/>
</svg>

对应这样一条连续的贝塞尔曲线:

【动画进阶】当路径动画遇到滚动驱动!

将对应的路径应用在 offset-path: path 中:

<div>
div:nth-child(2) {
    width: 40px;
    height: 40px;
    background: linear-gradient(#fc0, #f0c);
    offset-path: path('M 10 80 C 80 10, 130 10, 190 80 S 300 150, 360 80');
}
@keyframes move {
    0% {
        offset-distance: 0%;
    }
    100% {
        offset-distance: 100%;
    }
}

可以得到如下运动效果:

【动画进阶】当路径动画遇到滚动驱动!

可以看到,元素是沿着贝塞尔曲线的路径进行运动的,并且,由于这次没有限制死 offset-rotate,元素的朝向也是跟随路径的朝向一直变化的。(可以联想成开车的时候,车头一直跟随道路会进行变化的,带动整个车身的角度变化)

完整的 Demo 你可以戳这里:CodePen Demo -- CSS Motion Path Demo

Amazing!路径动画配合滚动驱动

好,终于,到这里,你应该已经大致了解了什么是路径动画 motion-path,什么是滚动驱动 scroll-driven

我们可以尝试把这两个东西组合在一起。

假设,我们有这么个 HTML 结构:

<div class="g-container">
    <div class="ele"></div>
</div>
body {
    width: 100%;
    height: 100%;
    background: conic-gradient(
        #fff,
        #fff 90deg,
        #ddd 90deg,
        #ddd 180deg,
        #fff 180deg,
        #fff 270deg,
        #ddd 270deg
    );
    background-size: 50px 50px;
}
.g-container {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, 0);
    width: 700px;
    height: 2000px;
}
.ele {
    position: absolute;
    width: 40px;
    height: 40px;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    background: linear-gradient(270deg, #65d060, #0887ec);
}

简单解释一下:

  1. 为了方便理解,我把 body 的背景设置成了格子背景
  2. .g-container 是一个远比屏幕高度高的容器,方便整个页面进行滚动
  3. .ele 是一个小三角形

目前,整个页面是这样的:

【动画进阶】当路径动画遇到滚动驱动!

下面,我们给 .ele设置一个 offset-path 路径:

.ele {
    position: absolute;
    width: 40px;
    height: 40px;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    background: linear-gradient(270deg, #65d060, #0887ec);
    offset-path: path("M 350 40 C 1000 1000, -350 1000, 350 1960");
    animation: move 4s linear infinite;
}

@keyframes move {
    0% {
        offset-distance: 0%;
    }
    50% {
        transform: scale(2.5);
    }
    100% {
        offset-distance: 100%;
    }
}

其中的核心就是 offset-path: path("M 350 40 C 1000 1000, -350 1000, 350 1960") 这里面,有一个利用 3 次贝塞尔曲线画出来的路径。

并且,我们给它加上了 offset-distance: 0offset-distance: 100% 的动画效果,目前,整个效果是这样的:

【动画进阶】当路径动画遇到滚动驱动!

可以看到,小三角形,按照特定的路径在进行运动。

为了更好的理解这个动画,我们可以利用 SVG,把这个运动的路径给画出来:

<div class="g-container">
    <svg class="g-svg" width="400" height="160" xmlns="http://www.w3.org/2000/svg">
        <path id="svgpath" d="M 350 40 C 1000 1000, -350 1000, 350 1960" stroke="black" fill="transparent" />
    </svg>
    <div class="ele"></div>
</div>
.g-svg {
    position: absolute;
    top: 0;
    left: 50%;
    width: 700px;
    height: 2000px;
    transform: translate(-50%, 0);
}
#svgpath {
    stroke: #9bc9de;
    stroke-width: 3px;
    stroke-dasharray: 2108, 2108;
    animation: lineMove 4s linear;
}
@keyframes lineMove {
    0% {
        stroke-dashoffset: 2108;
    }
    100% {
        stroke-dashoffset: 0;
    }
}

我们利用 SVG 路径,成功的将运动的路径绘制了出来,并且,利用 stroke-dasharraystroke-dashoffset,实现了一条线条动画,控制它和小三角形的 motion-path 动画保持一致。

要看懂 stroke-dasharraystroke-dashoffset 实现的线条动画,可能需要翻阅:【Web动画】SVG 线条动画入门

这样,现在,我们就得到了这么一个动画效果:

【动画进阶】当路径动画遇到滚动驱动!

到这里,其实还没有运用上滚动驱动,现在,我们把上述经由时间控制的动画效果,交给页面的滚动。

简单改造上述 CSS 代码:

.ele {
    position: absolute;
    width: 40px;
    height: 40px;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    offset-path: path("M 350 40 C 1000 1000, -350 1000, 350 1960");
    background: linear-gradient(270deg, #65d060, #0887ec);
    animation: move 4s linear;
    animation-timeline: scroll(root);
}

#svgpath {
    stroke: #9bc9de;
    stroke-width: 3px;
    stroke-dasharray: 2108, 2108;
    animation: lineMove 4s linear;
    animation-timeline: scroll(root);
}

改动比较简单:

  1. 去掉两个动画效果的 infinite 关键字
  2. 添加上 animation-timeline: scroll(root)

此时,我们就可以利用页面的滚动,控制整个动画效果:

【动画进阶】当路径动画遇到滚动驱动!

完整的 DEMO,你可以戳这里:CodePen Demo -- Scroll Driven & motion path & SVG stroke-dasharray Demo

在灵活掌握了上述内容后,我们就可以利用路径动画及滚动驱动创造出各种妙趣横生的动画效果!

下面是我综合利用各种技巧,实现的一个纯 CSS 滚动动画效果,感受一下:

【动画进阶】当路径动画遇到滚动驱动!

上述案例中,除了本文介绍的所有内容外,使用了本文没有提及的滚动驱动 API 中的 animation-range以及 CSS 与布局相关的 shape-outside 属性,如果不太了解这两个属性,需要自行补充相关知识。

Amazing!是不是非常的酷炫有意思,到今天,这种效果已经是纯 CSS 代码就能实现完成的了!

完整的代码基于上述的 DEMO 进行扩展得到,就不贴出来了,感兴趣的可以猛戳:CodePen Demo - CSS Scroll Driven

Can i Use - CSS Scroll Driven

来看看 CSS Scroll Driven 相关的 API 目前的兼容性如何?截止至 2023-09-09,基于 Can i Use - Animation-timeline 的兼容性如下:

【动画进阶】当路径动画遇到滚动驱动!

可以看到 animation-timeline 已经从 Chrome 115 版本正式得到支持,并且其它浏览器也已经开始大力跟进,让我们给时间一点时间,相信很快 CSS Scroll Driven 会更多的应用于生产环境,创造出各种以往需要借助 JavaScript 才能实现的动画。

而当路径动画遇到滚动驱动,势必会创造出各种妙趣横生的效果,更多有趣的效果组合等待我们去探索发现。

最后

好了,本文到此结束,希望对你有所收获。

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。文章来源地址https://www.toymoban.com/news/detail-709734.html

到了这里,关于【动画进阶】当路径动画遇到滚动驱动!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CSS 滚动驱动动画 view-timeline (view-timeline-name ❤️ view-timeline-axis )

    我们之前在 scroll() 中提到了一个因为绝对定位导致滚动无效的问题, 并使用 scroll-timeline 成功解决了这个问题, 而 scroll-timeline 起到的作用就是指定到底是哪个元素提供 scroll progress timeline . 与此相似, view-timeline 定义了一个具名的 view progress timeline , 通过滚动容器( scroller )中的某

    2024年02月08日
    浏览(28)
  • vue 监听滚动条 页面滚动动画

    以页面底部的“回到顶部”功能为例,滚动动画的实现思路是,当点击按钮时,获取当前滚动条的位置,调用定时器函数,每个时间间隔对滚动条的位置递减,直至减小到0,清除定时器,即可回到页面顶部。 当滚动条没有离开首页的一个屏幕高度时,“回到顶部”按钮应设

    2024年02月06日
    浏览(35)
  • unity实现数字滚动动画效果

    要在 Unity 中实现数字滚动动画效果,你可以使用以下步骤: 创建一个新的 Unity 项目。 在场景中添加一个 UI 文本控件。 在 C# 脚本中,使用 coroutine 实现动画效果。 在每一帧中更新 UI 文本的数字,并通过计算得出下一个数字的位置。 在动画结束后,使用 StopCoroutine 停止动画

    2024年02月10日
    浏览(35)
  • 实现对一个元素的滚动条进行平滑滚动至顶部的动画效果

    1.elementUI中的平滑滚动至顶部的动画效果代码 2.将上面的代码简化 3.继续简化代码 使用 Element.scrollTo 方法并使用 scroll-behavior: smooth 的简化代码示例: 首先,在你的CSS样式表中加入以下代码: 这会将平滑滚动的效果应用到整个页面。 然后,使用 scrollTo 方法在JavaScript中触发滚

    2024年02月11日
    浏览(31)
  • unity | 动画模块之滚动选项框

    一、效果动画 如果不是你们想要的,就省的你们继续往下看了  二、作者的话 对于我来说,计算一大堆数据很繁琐,就写了点简单的 三、基本功的要求 需要会使用Scroll View 四、进入正题  1.先做一个scrollView把自己想做的东西放进去 2.接下来的难度就是,当方块块移动到指定

    2024年02月03日
    浏览(25)
  • 使用scrollTo/scrollTop让页面元素滚动到指定位置, 并设置滚动动画

    当容器有滚动条时,有时需要点击 试图 或 节点 将页面滚动到指定元素位置 比如父元素设置了 overflow: hidden; ,当元素里的内容超过元素本身的高度时, 就会出现滚动条, 那么鼠标滑动的距离就是其滚动距离. scrollTop属性 scrollTop 就是指 “元素中的内容” 超出 “元素上边界” 的

    2023年04月27日
    浏览(66)
  • CSS实现文本和图片无限滚动动画

    Demo图如下:

    2024年01月24日
    浏览(54)
  • vue 基于原生动画的自动滚动表格

    公司展示大屏需要写滚动表格,通过滚动播放数据,自己随便摸了一个基于动画的自动滚动表格 根据每行的大小和设置的每行滚动时间设置滚动位置,动态添加动画,并把数组第一项移动到最后一项,并订阅该动画结束的事件,在结束时循环执行该操作。 可自定义单元格或

    2024年02月05日
    浏览(22)
  • Qt图片定时滚动播放器+透明过渡动画

    Qt图片浏览器 QT制作一个图片播放器 Qt中自适应的label+pixmap充满窗口后,无法缩小只能放大 Qt的动画类修改透明度来实现上下两张图片的切换效果 解决:[QWidget::paintEngine: Should no longer be called QPainter::begin: Paint device returned engine == 0, type: 1] 可以显示jpg、jpeg、png、bmp。可以从电脑

    2024年02月15日
    浏览(27)
  • 膜拜!用最少的代码却实现了最牛逼的滚动动画!

    大家好,我是 程序视点 的小二哥!今天小二哥带领大家学习如何使用最少的代码创建令人叹为观止的滚动动画~ 在聊 ScrollTrigger 插件之前我们先简单了解下 GSAP 。 GreenSock 动画平台 (GSAP) 可为 JavaScript 可以操作的任何内容(CSS 属性、SVG、React、画布、通用对象等)动画化,并

    2024年02月14日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包