当前位置: 首页 > 科技观察

精湛的合作!文字轮播和图片轮播?CSS很简单

时间:2023-03-20 19:12:39 科技观察

今天分享一个可以在实际业务中使用的动画技术。巧妙地利用逐帧动画和补间动画,实现无限循环的轮播效果,就像这样:看到上面的示意图,有同学不禁要问,这不就是一个很简单的位移动画吗?简单分析一下,表面上看好像只有元素的transform:translate()在移动,但是注意这里有两个难点:这是一个无限轮播效果,我们的动画需要支持无限轮播切换任意数量的元素。因为是轮播,跑到最后一个的时候,动画需要切到第一个元素。此时,你可以停下来想一想。如果有20个元素,你需要做一个类似的无限轮播,用CSS来实现,你会怎么做?逐帧动画控制整体切换首先,我需要使用逐帧动画效果,也称为stepeasing函数,使用animation-timing-function中的steps,语法如下:{/*关键字值*/animation-timing-function:step-start;动画计时功能:step-end;/*函数值*/animation-timing-function:steps(6,start)animation-timing-function:steps(4,end);}如果对steps的语法不是很熟悉,强烈推荐那你先看看我的文章——简单来说就是CSS动画[1],它对理解本文起着至关重要的作用。好吧,还是拿文章开头的例子来说,假设我们有这样一个HTML结构:

  • Loremipsum1111111
  • Loremipsum2222222
  • Loremipsum3333333
  • Loremipsum4444444
  • Loremipsum5555555
  • Loremipsum6666666
/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;弹性方向:列;动画:移动calc(var(--speed)*var(--s))steps(var(--s))infinite;}ulli{width:100%;}@keyframesmove{0%{transform:translate(0,0);}100%{transform:translate(0,calc(var(--s)*var(--h)*-1px));}}看到上面的CSS变量不要惊慌,其实很好理解:calc(var(--speed)*var(--s)):单个动画的耗时*carousel的个数,即是,总动画持续时间。steps(var(--s))是逐帧动画的帧数,这里是steps(6),很好理解。calc(var(--s)*var(--h)*-1px))单个li容器的高度*轮播数量,其实就是ul的整体高度,用来设置结束逐帧动画的点。上面的效果其实是这样的:如果给容器加上overflow:hidden,效果是这样的:这样,我们就得到了整体的结构,至少,整个效果是循环的。不过由于只是逐帧动画,所以只能看到切换,而没有每帧之间的过渡动??画效果。那么,接下来,就要介绍一下补间动画了。使用补间动画实现两组数据的切换我们需要使用补间动画来实现动态切换的效果。这一步其实很简单。我们要做的就是使用transform将一组数据从状态A转移到状态B。如果单独拿出一个来演示,一般代码如下:
  • Loremipsum1111111
  • Loremipsum2222222
  • Loremipsum3333333
  • Loremipsum4444444
  • Loremipsum5555555
  • Loremipsum6666666
  • :root{--h:36;--speed:1.2s;}ulli{height:36px;动画:liMovecalc(var(--speed))infinite;}@keyframesliMove{0%{transform:translate(0,0);}80%,100%{变换:翻译(0,-36px);}}一个很简单的动画:bgg1基于上面的效果,如果我们把开头提到的逐帧动画和这里这个tween动画结合起来,ul的整体运动,li的单独运动叠加together::root{//轮播数量--s:6;//单个li容器的高度--h:36;//单个动画时长--speed:1.5s;}.g-container{width:300px;height:calc(var(--h)*1px);}ul{display:flex;弹性方向:列;动画:移动calc(var(--speed)*var(--s))steps(var(--s))infinite;}ulli{width:100%;动画片:liMovecalc(var(--speed))infinite;}@keyframesmove{0%{transform:translate(0,0);}100%{transform:translate(0,calc(var(--s)*var(--h)*-1px));}}@keyframesliMove{0%{transform:translate(0,0);}80%,100%{变换:翻译(0,计算(var(--h)*-1px));}}可以得到这样的效果:哇,发生了神奇的化学反应!基于逐帧动画和补间动画的结合,我们差不多实现了一个轮播效果当然,还有一点瑕疵。可以看到最后一组数据从第六组数据transform到一组空数据:末尾填充了头部的第一组数据。真正开发过轮播的同学一定知道,到这里,其实也好办。我们只需要在末尾添加一组标头的第一个数据:转换我们的HTML:
    • Loremipsum1111111
    • Loremipsum2222222
    • Loremipsum3333333
    • Loremipsum4444444
    • Loremipsum5555555
    • Loremipsum6666666
    • Loremipsum1111111
    这样,我们再看看效果:漂亮!如果还是一头雾水,我们给容器添加overflow:hidden,实际效果如下,通过最后一组追加数据,我们的整个动画刚好完美衔接,一个完美的轮播效果:完整代码,大家可以点击here:CodePenDemo--VerticalInfinityLoop[2]Horizo??ntalinfinitycarousel当然实现了垂直的轮播,水平的效果也是一样的。另外,我们可以在HTML结构中的style中填写CSS变量值,传入实际的lis个数,根据lis个数适配不同的动画:
  • Loremipsum1111111
  • Loremipsum2222222
  • Loremipsum3333333
  • Loremipsum4444444
  • Loremipsum5555555
  • Loremipsum6666666
  • Loremipsum1111111
  • /div>整个动画的CSS代码基本相同,我们只需要改变两个动画的transform值,由垂直位移改为水平位移::root{--w:300;--speed:1.5s;}.g-container{width:calc(--w*1px);溢出:隐藏;}ul{显示:弹性;弹性包装:nowrap;动画:移动calc(var(--speed)*var(--s))steps(var(--s))infinite;}ulli{flex-shrink:0;宽度:100%;高度:100%;动画:liMovecalc(var(--speed))infinite;}@keyframesmove{0%{transform:translate(0,0);}100%{转换:翻译(计算(变量(--s)*var(--w)*-1px),0);}}@keyframesliMove{0%{transform:translate(0,0);}80%,100%{变换:翻译(calc(var(--w)*-1px),0);}}这样,我们就可以很方便的转换成水平效果了:完整代码,可以点击这里:CodePenDemo--Horizo??ntalInfinityLoop[3]carousel?没关系,上面只是文字版的轮播图,万一是图片呢?没问题,方法是一样的。基于以上代码,我们可以很容易的修改得到图片版的轮播效果。代码都是一样的,就不一一列举了,直接看效果吧:完整代码可以点击这里:CodePenDemo——水平图像无限循环[4]。一旦你掌握了这个技巧,你就可以将它应用到许多只需要简化版本的轮播效果中。简单总结一下,一个很有意思的技巧:用逐帧动画来实现整体的轮播循环效果。使用补间动画实现从状态A到状态B的具体动画效果。逐帧动画配合补间动画形成整体的轮播效果。通过在HTML结构的末尾添加一组头部数据,实现了整体动画的衔接。通过HTML元素的style标签,使用CSS变量,填写实际参与循环的DOM数量,就可以连接JavaScript和CSS。终于OK了,本文到此结束,希望本文对你有所帮助:)参考[1]深入浅出CSS动画:https://github.com/chokcoco/iCSS/issues/141。[2]CodePen演示——垂直无限循环:https://codepen.io/Chokcoco/pen/RwQVByx。[3]CodePen演示——水平无限循环:https://codepen.io/Chokcoco/pen/JjpNBXY。[4]CodePenDemo--水平图像无限循环:https://codepen.io/Chokcoco/pen/GRQvqgq。[5]Github--iCSS:https://github.com/chokcoco/iCSS。