2022年7月9日

css3实现雪碧图帧动画(转-完善)

作者 admin

从网上查到了相关资料,转过来研究学习一下,

背景:
此需求是在html界面实现,纯原生,没有像vue生命周期那些东西。

场景:
一个单纯的图片背景,想要在上面加个动图。一瞬间脑子里想到两个方案:
一:最省前端功夫的:ui压缩一个gif图出来
二:需要前端写点代码的:把ui提供的多张图片,利用css3动画,进行动画切换,达到动图的效果

情况一:ui压缩出的gif出现白边的问题,就不太好看,而且ui已经尽力了。。。
效果图:

情况二:使用css3动画属性,也发现了不适用的问题:
效果图:截图不能展示问题

老老实实使用css3.keyframe和animation来实现,这里也发现了问题,图片够小,即使预先在head加载了图片,但是没有添加到body中,可以在network看到图片加载成功,然后在动画里使用延迟,在qq、谷歌均可以正常加载,唯独在谷歌出现依旧出现闪烁。
基于此两种解决方案:

1:在head中写一个js,其目的是,快于页面加载,就生成img标签,赋值图片路径,append到页面。
间接实现图片预先加载,而后进行css3帧动画,当然你的页面不需要用到他,你可以隐藏掉。(此方案不太优雅,但能成事)

图片形式:

js:

for(var i = 0;i<10;i++){
  var img = new Image()
  img.onload = await function () {}.bind(this)
  img.src='/static/img/'+i+'_03.png'
  document.body.append(img)
}

.frame-logo .lo-wrap .img-bg{
  width: 440px;
  height: 424px;
  display: flex;
  position: absolute;
  top: 3vh;
  left: 9vw;
  background: url('/static/img/frame1/1_03.png');
  background-size:cover;
  animation: identifier_p 2s infinite;
}
@keyframes identifier_p {
  0% {
    background: url('/static/img/frame1/1_03.png');
  }
  7% {
    background: url('/static/img/frame1/2_03.png');
  }
  14% {
    background: url('/static/img/frame1/3_03.png');
  }
  21% {
    background: url('/static/img/frame1/4_03.png');
  }
  28% {
    background: url('/static/img/frame1/5_03.png');
  }
  35% {
    background: url('/static/img/frame1/6_03.png');
  }
  42% {
    background: url('/static/img/frame1/7_03.png');
  }
  49% {
    background: url('/static/img/frame1/8_03.png');
  }
  56% {
    background: url('/static/img/frame1/9_03.png');
  }
  63% {
    background: url('/static/img/frame1/10_03.png');
  }
  70% {
    background: url('/static/img/frame1/11_03.png');
  }
  77% {
    background: url('/static/img/frame1/12_03.png');
  }
  84% {
    background: url('/static/img/frame1/13_03.png');
  }
  91% {
    background: url('/static/img/frame1/14_03.png');
  }
  98% {
    background: url('/static/img/frame1/14_03.png');
  }
  100% {
    background: url('/static/img/frame1/1_03.png');
  }
}


2:使用雪碧图进行实现,将多张帧的图,合成雪碧图,然后改变位置进行实现。
animation: identifier_p 2s steps(1, start) infinite;这行代码中的steps(1, start)是实现的关键,如果没有他,这个动画相当可怕,等同于看一张不停的改变定位的背景图。有了他才能真正称为是“帧动画”,可以说是相当丝滑了,比gif体验好多了。

图片形式:

css:

.frame-logo .lo-wrap .img-bg{
  width: 440px;
  height: 424px;
  display: flex;
  position: absolute;
  top: 3vh;
  left: 9vw;
  background: url('/static/img/test/css_sprites.png');
  background-size:cover;
  animation: identifier_p 2s  steps(1, start) infinite;
//steps:(number,star/end) 
}

@keyframes identifier_p {
  0% {
  background: url('/static/img/test/css_sprites.png') -10px -10px;
  }
  7% {
  background: url('/static/img/test/css_sprites.png') -488px -10px;
  }
  14% {
  background: url('/static/img/test/css_sprites.png') -10px -474px;
  }
  21% {
  background: url('/static/img/test/css_sprites.png') -488px -474px;
  }
  28% {
  background: url('/static/img/test/css_sprites.png') -966px -10px;
  }
  35% {
  background: url('/static/img/test/css_sprites.png') -966px -474px;
  }
  42% {
  background: url('/static/img/test/css_sprites.png') -10px -938px;
  }
  49% {
  background: url('/static/img/test/css_sprites.png')  -488px -938px;
  }
  56% {
  background: url('/static/img/test/css_sprites.png') -966px -938px;
  }
  63% {
    background: url('/static/img/test/css_sprites.png') -1444px -10px;
  }
  70% {
    background: url('/static/img/test/css_sprites.png') -1444px -474px;
  }
  77% {
    background: url('/static/img/test/css_sprites.png') -1444px -938px;
  }
  84% {
    background: url('/static/img/test/css_sprites.png')  -10px -1402px;
  }
  91% {
    background: url('/static/img/test/css_sprites.png') -488px -1402px;
  }
  98% {
    background: url('/static/img/test/css_sprites.png') -10px -1402px;
  }
  100% {
  background: url('/static/img/test/css_sprites.png') -488px -1402px;
  }
}

原文地址 :https://blog.csdn.net/qq_44706619/article/details/121426057

补充 :

Steps(<number_of_steps>,<direction>)

方向为”start”表示一个左–持续函数,在动画开始时,动画的第一段将会马上完成。以左侧端点为起点,立即跳到第一个step的结尾处。它会立即跳到第一段的结束并且保持这样的状态直到第一步的持续时间结束。后面的每一帧都将按照此模式来完成动画。

方向为”end”表示一个右–持续函数。动画执行时,在每一帧里,动画保持当前状态直到这一段的持续时间完成,才会跳到下一步的起点,后面的每一帧都按照这个模式来进行,在最后一帧的起点,等到这一帧的持续时间结束,整个动画的执行也已经结束,执行动画的元素来不及跳到这一帧的终点,直接回到了整个动画起点,开始了第二次动画。每个选择本质上从一个不同的面移动这个元素并且将产生一个不同的位置在这个相同的动画里。
这面是示例图: