Web中多种实现动画的方案
前一段时间在做圣诞节运营活动页面的时候,UI给了各种酷炫的动画,看是好看,但是实现起来,头发就得遭殃了。
为此,总结了几种Web中多种实现动画的方案。
1.css3-transform
作为一名优秀的前端开发工程师(切图仔),能自己手动实现的动画绝不依赖于UI,为此css3提供了transform这一工具,其中的多个属性能满足我们的部分功能。
1.1 旋转rotate
rotate(<angle>) :通过指定的角度参数对原元素指定一个2D rotation(2D 旋转),需先有transform-origin属性的定义。transform-origin定义的是旋转的基点,其中angle是指旋转角度,如果设置的值为正数表示顺时针旋转,如果设置的值为负数,则表示逆时针旋转。
如:transform:rotate(30deg):
1.2 移动translate
移动translate我们分为三种情况:translate(x,y)水平方向和垂直方向同时移动(也就是X轴和Y轴同时移动);translateX(x)仅水平方向移动(X轴移动);translateY(Y)仅垂直方向移动(Y轴移动),具体使用方法如下:
1.translate(<translation-value>[, <translation-value>]) :通过矢量[tx, ty]指定一个2D translation,tx 是第一个过渡值参数,ty 是第二个过渡值参数选项。如果 未被提供,则ty以 0 作为其值。也就是translate(x,y),它表示对象进行平移,按照设定的x,y参数值,当值为负数时,反方向移动物体,其基点默认为元素 中心点,也可以根据transform-origin进行改变基点。如transform:translate(100px,20px):
2.translateX(<translation-value>) : 通过给定一个X方向上的数目指定一个translation。只向x轴进行移动元素,同样其基点是元素中心点,也可以根据transform-origin改变基点位置。如:transform:translateX(100px):
3.translateY(<translation-value>) :通过给定Y方向的数目指定一个translation。只向Y轴进行移动,基点在元素心点,可以通过transform-origin改变基点位置。如:transform:translateY(20px):
1.3 缩放scale
缩放scale和移动translate是极其相似,他也具有三种情况:scale(x,y)使元素水平方向和垂直方向同时缩放(也就是X轴和Y轴同时缩放);scaleX(x)元素仅水平方向缩放(X轴缩放);scaleY(y)元素仅垂直方向缩放(Y轴缩放),但它们具有相同的缩放中心点和基数,其中心点就是元素的中心位置,缩放基数为1,如果其值大于1元素就放大,反之其值小于1,元素缩小。下面我们具体来看看这三种情况具体使用方法:
1.scale(<number>[, <number>]):提供执行[sx,sy]缩放矢量的两个参数指定一个2D scale(2D缩放)。如果第二个参数未提供,则取与第一个参数一样的值。scale(X,Y)是用于对元素进行缩放,可以通过transform-origin对元素的基点进行设置,同样基点在元素中心位置;基中X表示水平方向缩放的倍数,Y表示垂直方向的缩放倍数,而Y是一个可选参数,如果没有设置Y值,则表示X,Y两个方向的缩放倍数是一样的。并以X为准。如:transform:scale(2,1.5):
2.scaleX(<number>) : 使用 [sx,1] 缩放矢量执行缩放操作,sx为所需参数。scaleX表示元素只在X轴(水平方向)缩放元素,他的默认值是(1,1),其基点一样是在元素的中心位置,我们同样是通过transform-origin来改变元素的基点。如:transform:scaleX(2):
3.scaleY(<number>) : 使用 [1,sy] 缩放矢量执行缩放操作,sy为所需参数。scaleY表示元素只在Y轴(垂直方向)缩放元素,其基点同样是在元素中心位置,可以通过transform-origin来改变元素的基点。如transform:scaleY(2):
1.4 扭曲skew
扭曲skew和translate、scale一样同样具有三种情况:skew(x,y)使元素在水平和垂直方向同时扭曲(X轴和Y轴同时按一定的角度值进行扭曲变形);skewX(x)仅使元素在水平方向扭曲变形(X轴扭曲变形);skewY(y)仅使元素在垂直方向扭曲变形(Y轴扭曲变形),具体使用如下:
1.skew(<angle> [, <angle>]) :X轴Y轴上的skew transformation(斜切变换)。第一个参数对应X轴,第二个参数对应Y轴。如果第二个参数未提供,则值为0,也就是Y轴方向上无斜切。skew是用来对元素进行扭曲变行,第一个参数是水平方向扭曲角度,第二个参数是垂直方向扭曲角度。其中第二个参数是可选参数,如果没有设置第二个参数,那么Y轴为0deg。同样是以元素中心为基点,我们也可以通过transform-origin来改变元素的基点位置。如:transform:skew(30deg,10deg):
2.skewX(<angle>) : 按给定的角度沿X轴指定一个skew transformation(斜切变换)。skewX是使元素以其中心为基点,并在水平方向(X轴)进行扭曲变行,同样可以通过transform-origin来改变元素的基点。如:transform:skewX(30deg)
3.skewY(<angle>) : 按给定的角度沿Y轴指定一个skew transformation(斜切变换)。skewY是用来设置元素以其中心为基点并按给定的角度在垂直方向(Y轴)扭曲变形。同样我们可以通过transform-origin来改变元素的基点。如:transform:skewY(10deg)
2.序列帧动画
当基本的transform无法满足比较复杂的动画时,我们可以考虑才用序列帧动画的形式来实现。
原理很简单,就是将一张动图截成若干帧的静态图,然后利用程序在短时间内切换图片,来达到视觉上的动画。实现也很简单,就是每隔一段时间切换一次展示区域所能看见的图片即可。
由于可视区域中图片的变换不是渐变,而是瞬变的,因此我们需要借助于css中的animation-timing-function中的steps()来实现。steps(<integer>[, [ start | end ] ]?)
:接受两个参数的步进函数。第一个参数必须为正整数,指定函数的步数。第二个参数取值可以是start或end,指定每一步的值发生变化的时间点。第二个参数是可选的,默认值为end
工作机制如图:
因此,我们需要像使用雪碧图一样,将多张静态图片合成一张,然后当做动画区域的背景图,利用animation
来改变background-position
便能实现序列帧动画。
提供一个demo代码:
div{
background-image: url('image/image.jpeg');
background-repeat: no-repeat;
height: 345px;
width: 235px;
animation: move 1s steps(1,end) infinite;
}
@keyframes move{
0%{
background-position: 0px 0;
}
14.285%{
background-position: -180px 0;
}
28.571%{
background-position: -369px 0;
}
42.857%{
background-position: -609px 0;
}
57.143%{
background-position: -35px -424px;
}
71.429%{
background-position: -235px -424px;
}
85.714%{
background-position: -435px -424px;
}
100%{
}
}
3.gif、apng、webp
当css动画无法实现UI要求的动画时,我们又懒于用更复杂的方式去实现,那么让UI直接导出一张动图最好不过了。
那么,多种动图格式,才用哪种呢?莫急,且听我娓娓道来。
1.GIF 是一个非常古老的格式,1987 年诞生,最后一个版本是 1989 年。
2.APNG 格式是 PNG 的扩展,第一帧储存方式和普通的 PNG 一样在 IDAT 区段中,APNG 只是新增了三种区段,所以如果一个软件只支持 PNG 而不支持 APNG 的话,依旧可以显示出图片的第一帧,只是不能动罢了。APNG 新增的三种区段分别为:
- acTL (animation control) 用来存放帧数和播放次数,整个文件只有一个区段
- fcTL (frame control) 用来存放每一帧的高、宽、位置、延时等信息,每一帧一个区段
- fdAT (frame data) 用来存放除了第一帧以外后面每一帧的图片数据,采用 Deflate 压缩,每一帧一个区段
3.WebP,Google 在 2010 年推出的全部通吃的图片格式,为什么叫全部通吃呢?因为他既可以有损(替代 JPEG)也可以无损(替代 PNG),还可以动(替代 GIF),并且在压缩率上全面超越了这三种常用的格式。
压缩率
GIF 采用的是 LZW,而 APNG 采用的是 Deflate,再加上 APNG 继承了 PNG 的 filter,利用相邻像素的相似性使压缩率大大提高
颜色
GIF 每个像素只有 8 bit,也就是说只有 256 种颜色,于是很多人误以为 GIF 不支持 24 bit RGB,但实际上,GIF 的限制是每一帧最多只能有 256 种颜色,但是每种颜色可以是 24 bit 的。不过即使是这样,256 种颜色还是太少了,这就导致了 GIF 的画质都比较差。
而 APNG 和 WebP 则完全没有这方面的限制。
透明
GIF 虽然也支持透明,但是他只支持将某个颜色标记成透明,也就是说他不支持半透明,只支持完全透明或者完全不透明。如果把一个边缘是半透明的图片转换成 GIF,就会出现另一个答案中提到的杂边问题。
而 APNG 和 WebP 都支持 8 bit alpha channel,透明度可以有 256 级。
兼容性
可能是 GIF 唯一的优势了吧。
几乎所有的浏览器都支持 GIF,而支持 APNG 的浏览器有 Chrome、Firefox、Safari 和 Opera,支持 WebP 的有 Chrome、Firefox、Edge 和 Opera
4.canvas、svga
canvas先是创建一个画板,然后在画板中通过操作点、线、面、图片以及dom元素的样式来实现变幻,在变幻过程中添加一些过渡态,便能得到我们想要的效果。
而svga与canvas类似,通过不断修改g这个dom节点的样式来实现变幻。
canvas和svga实现动画有一个好处,就是完全交由开发实现,并且h5提供了丰富的api供大家使用,理论上来说,只要代码足够优秀,什么动画都能实现。
在这,就不逐一介绍canvas和svga的api了,大家有兴趣的话可自行查阅文档。
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial
https://developer.mozilla.org/zh-CN/docs/Web/API/SVGAElement
5.lottie动画
lottie动画在浏览器中渲染的原理其实跟svga相似,也是通过不断地更改元素的样式来实现动画效果,但是lottie动画有一个很大的好处就是:不需要开发去手撕动画,由UI通过制图软件制作好动画,然后导出一个文件,里面包含有一个json文件(用于描述素材的运动轨迹)、一个html文件(用于预览该lottie动画)以及必要的素材,而开发只需要导入json和素材即可实现动画。
Lottie可以解决的问题:
1> 开发人员无需编写动画,只需加载
2> 多平台支持,一次设计多端使用
3> 解决设计提供的动效与实现不一致问题
4> 因为只是加载json文件,占用空间更小
5> 专业的人做专业的事,设计师安心做酷炫动画,开发者专心写逻辑
在业内,已经有很多基于web加载lottie的库,大家可以安心使用,并且兼容性也非常的好。
本文参考:
https://www.cnblogs.com/qianduanjingying/p/4937574.html
https://www.jayxon.com/gif-apng-webp/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。