CSS3动画和JS动画的区别
1.JS 实现的是帧动画(使用定时器,每隔一段时间,更改当前的元素)
2.CSS3 实现的是补间动画(过渡(加过渡只要状态发生改变产生动画)动画(多个节点来控制动画)性能会更好)
transition
transition是一个简单的动画属性,可以看作是是animation的简化版本,通常拿来配合事件触发使用,简单易用
transition的属性值:
transition-property:需要过渡的属性,也可以是all,不能用block,none等
transition-duration: 指定从一个属性到另一个属性过渡所要花费的时间。默认值为0,为0时,表示变化是瞬时的,看不到过渡效果
transiton-timing-function:就是过渡的动画类型。可用的类型有liner(匀速)、ease-in(减速)、ease-out(加速)ease-in-out(先加速再减速)、cubic-bezier:三次贝塞尔曲线,可以定制
transition-delay: 指定检测到过渡行为之后延迟一定时间后才开始进行执行
transition的特性:
transition需用事件触发【比如加个hover伪类】,不能在网页加载时自动发生,一次性,不能重复发生,除非一再触发,只有两个状态:开始和结束状态,一条transition规则只能定义一个属性
animation
animation-name:用来调用@keyframes定义好的动画,与@keyframes定义的动画名称一致
animation-duration:规定动画完成一个周期所花费的秒或毫秒。默认是 0
animation-timing-function:速度曲线,和transition-timing-function一样,可用的类型有liner(匀速)、ease-in(减速)、ease-out(加速)ease-in-out(先加速再减速)、cubic-bezier:三次贝塞尔曲线,可以定制
animation-delay:规定动画何时开始,默认是 0
animation-iteration-count:规定动画被播放的次数。默认是 1
animation-direction:normal 默认值,如果设置为normal时,动画每次循环都是向前(即按顺序)播放,alternate(轮流),动画播放在第偶数次向前播放,第奇数次向反方向播放(animation-iteration-count取值大于1时设置有效)
animation-play-state:running,可以通过该值将暂停的动画重新播放,这里的重新播放不是从元素动画的开始播放,而是从暂停的那个位置开始播放,paused,暂停播放
animation-fill-mode:默认情况下,动画结束后,元素的样式将回到起始状态,animation-fill-mode属性可以控制动画结束后元素的样式。主要具有四个属性值:none(默认,回到动画没开始时的状态。),forwards(动画结束后动画停留在结束状态),backwords(动画回到第一帧的状态),both(根据animation-direction轮流应用forwards和backwards规则)
区别:
1、transition 是过渡,是样式值的变化的过程,只有开始和结束;animation 其实也叫关键帧,通过和 keyframe 结合可以设置中间帧的一个状态;
2、animation 配合 @keyframe 可以不触发时间就触发这个过程,而 transition 需要通过 hover 或者 js 事件来配合触发;
3、animation 可以设置很多的属性,比如循环次数,动画结束的状态等等,transition 只能触发一次;
4、animation 可以结合 keyframe 设置每一帧,但是 transition 只有两帧,所以animation 动画更细腻些;
5、在性能方面:浏览器有一个主线程和排版线程;主线程一般是对 js 运行的、页面布局、生成位图等等,然后把生成好的位图传递给排版线程,而排版线程会通过 GPU 将位图绘制到页面上,也会向主线程请求位图等等;我们在用使用 aniamtion 的时候这样就可以改变很多属性,像我们改变了 width、height、postion 等等这些改变文档流的属性的时候就会引起,页面的回流和重绘,对性能影响就比较大,但是我们用 transition 的时候一般会结合 tansfrom 来进行旋转和缩放等不会生成新的位图,当然也就不会引起页面的重排了;
animation和transition的性能探究
现代浏览器通常由两个重要的线程组成。这两个线程一起工作完成绘制页面的任务:
- 主线程
- 合成线程
主线程需要做的任务如下:
- 运行Javascript
- 计算HTML元素的CSS样式
- layout (relayout)
- 将页面元素绘制成一张或多张位图
- 将位图发送给合成线程
合成线程主要任务是:
- 利用GPU将位图绘制到屏幕上
- 让主线程将可见的或即将可见的位图发给自己
- 计算哪部分页面是可见的
- 计算哪部分页面是即将可见的(当你的滚动页面的时候)
- 在你滚动时移动部分页面
在很长的一段时间内,主线程都在忙于运行Javascript和绘制大型元素。当它忙碌的时候,它就没空响应用户的输入了。
换个角度说,合成线程一直在尝试保证对用户输入的响应。它会在页面改变时每秒绘制60次页面,即使页面还不完整。
例如,当用户滚动一个页面时,合成线程会让主线程提供最新的可见部分的页面位图。然而主线程不能及时的响应。这时合成线程不会等待,它会绘制已有的页面位图。对于没有的部分则绘制白屏。
GPU
如今大多数手机、平板和电脑都带有了GPU芯片。它非常的特别,它很擅长做某些事情,又很不擅长做其他事情。
GPU在做如下操作时很快:
1.绘制东西到屏幕上
2.一次次绘制同一张位图到屏幕上
3.绘制同一张位图到不同的位置、旋转角度和缩放比例
GPU很不擅长做
1.加载位图到内存中
假设我们将一个页面元素的高度从100px渐变到200px,代码如下:
div {
height: 100px;
transition: height 1s linear;
}
div:hover {
height: 200px;
}
下图是一张主线程和合成线程的互相交互的时间线图。注意:黄色盒子的操作是潜在耗时较长的,蓝色盒子的操作是很快的。
可以看到有很多黄色的盒子,这意味着浏览器要做很多复杂的操作。这就表明这个transition动画很可能会卡。
在transition动画的每一帧中,浏览器都要做下relayout和repaint,然后将位图发送给GPU。之前我们提到了,加载位图到GPU内存中是很慢的。
浏览器之所以这么拼命的工作是因为元素在不停的变化。而且修改元素的高度可能会导致子元素的大小也会变化,所以浏览器不得不进行relayout。在relayout之后主线程还需要重新生成元素的位图。
transition: transform
所以高度的变化是很耗时的,有没有什么东西耗时更少呢?
假设我们将一个元素缩小到其一半大小。同时假设我们使用了transform来缩放元素。那么这个缩小动画的CSS如下:
div {
transform: scale(0.5);
transition: transform 1s linear;
}
div:hover {
transform: scale(1.0);
}
时间线图:
这次我们很少看到黄色盒子了,这就意味着这个动画可以很流畅!那么为什么transform的动画会和height的动画差别这么大呢?
依据规范,CSS transform属性并不会触发当前元素或附近元素的relayout。浏览器将当前元素视为一个整体,它会缩放、旋转、移动这一整个元素。
这样浏览器只需要在动画开始之时生成位图,然后将位图发送给GPU。之后浏览器不需要做额外的relayout和repaint,甚至不需要发送位图给GPU。浏览器只需要充分发挥GPU的长处:绘制同一张位图到不同的位置、旋转角度和缩放比例。