乐趣区

关于前端:文字轮播与图片轮播CSS-不在话下

明天,分享一个理论业务中可能用得上的动画技巧。

巧用逐帧动画,配合补间动画实现一个有限循环的轮播成果,像是这样:

看到上述示意图,有同学不禁会提问,这不是个非常简单的位移动画么?

咱们来简略剖析剖析,从外表上看,的确如同只有元素的 transform: translate() 在位移,然而留神,这里有两个难点:

  1. 这是个有限轮播的成果,咱们的动画须要反对任意多个元素的有限轮播切换
  2. 因为是轮播,所以,运行到最初一个的时候,须要动画切到第一个元素

到这里,你能够暂停思考一下,如果有 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 动画,它对了解本文起着至关重要的作用。

好的,还是文章以结尾的例子,假如咱们存在这样 HTML 构造:

<div class="g-container">
  <ul>
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
  </ul>
</div>

首先,咱们实现这样一个简略的布局:

在这里,要实现轮播成果,并且是任意个数,咱们能够借助 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 变量就慌了,其实很好了解:

  1. calc(var(--speed) * var(--s)):单次动画的耗时 * 轮播的个数,也就是总动画时长
  2. steps(var(--s)) 就是逐帧动画的帧数,这里也就是 steps(6),很好了解
  3. calc(var(--s) * var(--h) * -1px)) 单个 li 容器的高度 * 轮播的个数,其实就是 ul 的总体高度,用于设置逐帧动画的起点值

上述的成果,理论如下:

如果给容器增加上 overflow: hidden,就是这样的成果:

这样,咱们就失去了整体的构造,至多,整个成果是循环的。

然而因为只是逐帧动画,所以只能看到切换,然而每一帧之间,没有过渡动画成果。所以,接下来,咱们还得引入补间动画。

利用补间动画实现两组数据间的切换

咱们须要利用补间动画,实现动静的切换成果。

这一步,其实也非常简单,咱们要做的,就是将一组数据,利用 transform,从状态 A 位移到 状态 B。

独自拿出一个来演示的话,大抵的代码如下:

<div class="g-container">
  <ul style="--s: 6">
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
  </ul>
</div>
: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);
  }
}

非常简单的一个动画:

基于上述成果,咱们如果把一开始提到的 逐帧动画 和这里这个 补间动画 联合一下,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:

<div class="g-container">
  <ul>
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
    <!-- 开端补一个首条数据 -->
    <li>Lorem ipsum 1111111</li>
  </ul>
</div>

这样,咱们再看看成果:

Beautiful!如果你还有所纳闷,咱们给容器加上 overflow: hidden,实际效果如下,通过额定增加的最初一组数据,咱们的整个动画刚好完满的连接上,一个完满的轮播成果:

残缺的代码,你能够戳这里:CodePen Demo — Vertical Infinity Loop

横向有限轮播

当然,实现了竖直方向的轮播,横向的成果也是一样的。

并且,咱们能够通过在 HTML 构造中,通过 style 内填写 CSS 变量值,传入理论的 li 个数,以达到依据不同 li 个数适配不同动画:

<div class="g-container">
  <ul style="--s: 6">
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
    <!-- 开端补一个首尾数据 -->
    <li>Lorem ipsum 1111111</li>
  </ul>
</div>

整个动画的 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

轮播图?不在话下

OK,下面的只是文字版的轮播,那如果是图片呢?

没问题,办法都是一样的。基于上述的代码,咱们能够轻松地将它批改一下后失去图片版的轮播成果。

代码都是一样的,就不再列出来,间接看看成果:

残缺的代码,你能够戳这里:CodePen Demo — Horizontal Image Infinity Loop

把握了这个技巧之后,你能够将它使用在十分多只须要简化版的轮播成果之上。

再简略总结一下,十分有意思的技巧:

  1. 利用 逐帧动画,实现整体的轮播的循环成果
  2. 利用 补间动画 ,实现具体的 状态 A 状态 B * 的动画成果
  3. 逐帧动画 配合 补间动画 形成整体轮播的成果
  4. 通过向 HTML 构造开端补充一组头部数据,实现整体动画的连接
  5. 通过 HTML 元素的 style 标签,利用 CSS 变量,填入理论的参加循环的 DOM 个数,能够实现 JavaScript 与 CSS 的买通

最初

OK,本文到此结束,心愿本文对你有所帮忙 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 — iCSS 前端趣闻 😄

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

退出移动版