动画进阶 |
您所在的位置:网站首页 › css中的动画效果有哪些内容呢图片 › 动画进阶 |
今天,分享一个实际业务中能够用得上的动画技巧。 巧用逐帧动画,配合补间动画实现一个无限循环的轮播效果,像是这样: 看到上述示意图,有同学不禁会发问,这不是个非常简单的位移动画么? 我们来简单分析分析,从表面上看,确实好像只有元素的 transform: translate() 在位移,但是注意,这里有两个难点: 这是个无限轮播的效果,我们的动画需要支持任意多个元素的无限轮播切换。因为是轮播,所以,运行到最后一个的时候,需要动画切到第一个元素。到这里,你可以暂停思考一下,如果有 20 个元素,需要进行类似的无限轮播播报,使用 CSS 实现,你会怎么去做呢? 逐帧动画控制整体切换首先,我需要利用到逐帧动画效果,也被称为步骤缓动函数,利用的是 animation-timing-function 中,的 steps,语法如下: { /* Keyword values */ animation-timing-function: step-start; animation-timing-function: step-end; /* Function values */ animation-timing-function: steps(6, start) animation-timing-function: steps(4, end); }如果你对 steps 的语法还不是特别了解,强烈建议你先看看我的这篇文章 -- 深入浅出 CSS 动画[1],它对理解本文起着至关重要的作用。 好的,还是文章以开头的例子,假设我们存在这样 HTML 结构: Lorem ipsum 1111111 Lorem ipsum 2222222 Lorem ipsum 3333333 Lorem ipsum 4444444 Lorem ipsum 5555555 Lorem ipsum 6666666首先,我们实现这样一个简单的布局: 在这里,要实现轮播效果,并且是任意个数,我们可以借助 animation-timing-function: steps(): :root { // 轮播的个数 --s: 6; // 单个 li 容器的高度 --h: 36; // 单次动画的时长 --speed: 1.5s; } .g-container { width: 300px; height: calc(var(--h) * 1px); } ul { display: flex; flex-direction: column; animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite; } ul li { width: 100%; } @keyframes move { 0% { transform: translate(0, 0); } 100% { transform: translate(0, calc(var(--s) * var(--h) * -1px)); } }别看到上述有几个 CSS 变量就慌了,其实很好理解: calc(var(--speed) * var(--s)):单次动画的耗时 * 轮播的个数,也就是总动画时长。steps(var(--s)) 就是逐帧动画的帧数,这里也就是 steps(6),很好理解。calc(var(--s) * var(--h) * -1px)) 单个 li 容器的高度 * 轮播的个数,其实就是 ul 的总体高度,用于设置逐帧动画的终点值。上述的效果,实际如下: 如果给容器添加上 overflow: hidden,就是这样的效果: 这样,我们就得到了整体的结构,至少,整个效果是循环的。 但是由于只是逐帧动画,所以只能看到切换,但是每一帧之间,没有过渡动画效果。所以,接下来,我们还得引入补间动画。 利用补间动画实现两组数据间的切换我们需要利用补间动画,实现动态的切换效果。 这一步,其实也非常简单,我们要做的,就是将一组数据,利用 transform,从状态 A 位移到 状态 B。 单独拿出一个来演示的话,大致的代码如下: Lorem ipsum 1111111 Lorem ipsum 2222222 Lorem ipsum 3333333 Lorem ipsum 4444444 Lorem ipsum 5555555 Lorem ipsum 6666666 :root { --h: 36; --speed: 1.2s; } ul li { height: 36px; animation: liMove calc(var(--speed)) infinite; } @keyframes liMove { 0% { transform: translate(0, 0); } 80%, 100% { transform: translate(0, -36px); } }非常简单的一个动画: bgg1 基于上述效果,我们如果把一开始提到的 逐帧动画 和这里这个 补间动画 结合一下,ul 的整体移动,和 li 的 单个移动叠在在一起: :root { // 轮播的个数 --s: 6; // 单个 li 容器的高度 --h: 36; // 单次动画的时长 --speed: 1.5s; } .g-container { width: 300px; height: calc(var(--h) * 1px); } ul { display: flex; flex-direction: column; animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite; } ul li { width: 100%; animation: liMove calc(var(--speed)) infinite; } @keyframes move { 0% { transform: translate(0, 0); } 100% { transform: translate(0, calc(var(--s) * var(--h) * -1px)); } } @keyframes liMove { 0% { transform: translate(0, 0); } 80%, 100% { transform: translate(0, calc(var(--h) * -1px)); } }就能得到这样一个效果: Wow,神奇的化学反应产生了!基于 逐帧动画 和 补间动画 的结合,我们几乎实现了一个轮播效果。 当然,有一点瑕疵,可以看到,最后一组数据,是从第六组数据 transform 移动向了一组空数据: 实际开发过轮播的同学肯定知道,这里,其实也很好处理,我们只需要在末尾,补一组头部的第一个数据即可: 改造下我们的 HTML: Lorem ipsum 1111111 Lorem ipsum 2222222 Lorem ipsum 3333333 Lorem ipsum 4444444 Lorem ipsum 5555555 Lorem ipsum 6666666 Lorem ipsum 1111111这样,我们再看看效果: Beautiful!如果你还有所疑惑,我们给容器加上 overflow: hidden,实际效果如下,通过额外添加的最后一组数据,我们的整个动画刚好完美的衔接上,一个完美的轮播效果: 完整的代码,你可以戳这里:CodePen Demo -- Vertical Infinity Loop[2] 横向无限轮播当然,实现了竖直方向的轮播,横向的效果也是一样的。 并且,我们可以通过在 HTML 结构中,通过 style 内填写 CSS 变量值,传入实际的 li 个数,以达到根据不同 li 个数适配不同动画: Lorem ipsum 1111111 Lorem ipsum 2222222 Lorem ipsum 3333333 Lorem ipsum 4444444 Lorem ipsum 5555555 Lorem ipsum 6666666 Lorem ipsum 1111111整个动画的 CSS 代码基本是一致的,我们只需要改变两个动画的 transform 值,从竖直位移,改成水平位移即可: :root { --w: 300; --speed: 1.5s; } .g-container { width: calc(--w * 1px); overflow: hidden; } ul { display: flex; flex-wrap: nowrap; animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite; } ul li { flex-shrink: 0; width: 100%; height: 100%; animation: liMove calc(var(--speed)) infinite; } @keyframes move { 0% { transform: translate(0, 0); } 100% { transform: translate(calc(var(--s) * var(--w) * -1px), 0); } } @keyframes liMove { 0% { transform: translate(0, 0); } 80%, 100% { transform: translate(calc(var(--w) * -1px), 0); } }这样,我们就轻松的转化为了横向的效果: 完整的代码,你可以戳这里:CodePen Demo -- Horizontal Infinity Loop[3] 轮播图?不在话下OK,上面的只是文字版的轮播,那如果是图片呢? 没问题,方法都是一样的。基于上述的代码,我们可以轻松地将它修改一下后得到图片版的轮播效果。 代码都是一样的,就不再列出来,直接看看效果: 完整的代码,你可以戳这里:CodePen Demo -- Horizontal Image Infinity Loop[4] 掌握了这个技巧之后,你可以将它运用在非常多只需要简化版的轮播效果之上。 再简单总结一下,非常有意思的技巧: 利用 逐帧动画,实现整体的轮播的循环效果。利用 补间动画,实现具体的 *状态A 向 状态B 的动画效果。逐帧动画 配合 补间动画 构成整体轮播的效果。通过向 HTML 结构末尾补充一组头部数据,实现整体动画的衔接。通过 HTML 元素的 style 标签,利用 CSS 变量,填入实际的参与循环的 DOM 个数,可以实现 JavaScript 与 CSS 的打通。最后OK,本文到此结束,希望本文对你有所帮助 :) 参考资料[1]深入浅出 CSS 动画: https://github.com/chokcoco/iCSS/issues/141 [2]CodePen Demo -- Vertical Infinity Loop: https://codepen.io/Chokcoco/pen/RwQVByx [3]CodePen Demo -- Horizontal Infinity Loop: https://codepen.io/Chokcoco/pen/JjpNBXY [4]CodePen Demo -- Horizontal Image Infinity Loop: https://codepen.io/Chokcoco/pen/GRQvqgq [5]Github -- iCSS: https://github.com/chokcoco/iCSS |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |