wangjie-fourth 的个人博客

记录精彩的程序人生

目录
CSS动画
/      

CSS动画

动画是由许多静止的画面(桢),以一定的速度(如每秒30张)连续播放时,人类肉眼因视觉残像产生的错觉。

  • 帧:每个静止的画面都叫做帧;
动画的实现

1、通过定时器、改变样式来实现
image.png
setInterval的缺点就是只能刷新页面或者使用clearInterval来停止计时;而且这个动画渲染的性能是非常差的,每次定时器执行都是重新绘制页面(repaint)。

2、通过transition来实现
image.png
这里意思是指在1s后,将元素变成指定的样式。相比较上面那种方法,这种渲染性能更好。还可以在setTimeout设置秒数。

一、游览器渲染原理

游览器渲染过程

游览器在获取到服务器返回的代码后,会渲染指定的页面。这个过程有以下几步:

  • DOM:根据HTML构建HTML
  • CSSOM:根据CSS构建CSS
  • render tree:将俩棵树合并成一颗渲染树
  • Layout布局:定位(是否在文档流中)、计算大小(盒模型、计算大小和位置);
  • Paint绘制(把边框颜色、文字颜色、阴影等画出来)
  • Compose合成(根据层叠关系展示画面)

image.png

更新样式,重新渲染的过程

当最初页面渲染好后,后期我们可能会通过jscss代码来修改样式。比如说:

  • div.style.background='red'
  • div.style.displat= 'none'
  • div.classList.add('red')
  • div.remove()

通过上面的代码,我们就可以修改一个页面上的样式。这个时候游览器会如何重新渲染呢?

三种更新方式

当你通过代码修改某个CSS样式的时候,就会触发下面三种的某一种方式。可以通过查看CSS属性会以什么方式更新样式
1、JS/CSS > 样式 > 布局 > 绘制 > 合成
image.png

2、JS/CSS > 样式 > 绘制 > 合成
image.png

3、JS/CSS > 样式 > 合成
image.png

比如说:

  • 当使用div.remove,就会通过第一种方式来更新样式;
  • 当使用div.style.background='red',就会通过第二种方式来更新样式;
  • 当使用transform来改变样式的时候,就会通过第三种方式来更新样式;

参考信息:

CSS动画优化

参考Google团队的文章,常见的有:
1、JS优化

  • 使用requestAnimationFrame代替setTimeoutsetInterval

2、CSS优化

  • 使用will-changetranslate

二、transfrom

MDN transform,有四个常用功能:

  • 移动:translate
  • 缩放:scale
  • 旋转:rotate
  • 倾斜:skew

这里需要注意:

  • 一般都需要配合transition过渡动画;
  • inline元素不支持transform,需要先变成block元素

translate

translateZ相对于视点;视点就是含有perspective的父元素的正中心。
image.png

scale

rotate

image.png

skew

transfrom多重效果

1、组合使用

  • transform:none;取消所有
  • transform:scale(0.5) translate(-100%,-100%)

三、transition过渡

MDN transition用于补充中间动画,你只需要告诉它开始是什么样子,结束是什么样子。
1、语法

  • transition: 需要改变的css属性名 时长 过渡方式 延迟,比如说transition:width 200ms linear
  • 可以用逗号分隔俩个不同属性,比如说transition:width 200ms,top 400ms
  • 可以用all代表所有属性,比如说transition:all 200ms
  • 过渡的方式有:lineareaseease-inease-outease-in-outcubic-bezierstep-startstep-endsteps

2、注意
不是所有CSS属性都支持transition的。
(1)让一个元素从看的见到看不见
这里使用displate:none,是没有效果的。
image.png

这样写是直接消失的,而不是慢慢的消失

如果想慢慢消失的话,应该使用透明度opacity,但是opacity有个缺点,就是即使为0,它仍然占着位置。这时候,可以使用定时器或监听事件在元素消失后,移走这个节点。
image.png

3、假设中间还有一个变化
假设你想做的动画有三种状态,比如说从黑变成红,再变成白。这时候有俩种方法。
(1)使用俩次transform

  • .a经过transform,变成.b
  • .b经过transform,变成.c

这里可以使用setTimeout或者监听transitionend事件,来明确到达中间点。
image.png

(2)使用新的animation属性
image.png

四、animation属性

使用这个属性,只需要声明关键点样式是什么,中间帧会自动补充上去的。

@keyframe语法

mdn @keyframes语法有俩种写法:

  • fromto
    image.png
  • 百分数
    image.png

animation语法

语法格式如下:

animation: 时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充模式 | 是否暂停 | 动画名;
  • 时长:1s1000ms
  • 过渡方式:跟transition取值一样,如linear
  • 次数:32.4infinite无限次
  • 方向:reversealternatealternate-reverse
  • 填充模式:noneforwardsbackwardsboth
  • 是否暂停:pausedrunning

五、实例

使用transform实现跳动的心

image.png

*{
  margin: 0;
  padding:0;
  box-sizing:border-box;
}
#heart{
  margin: 100px;
  position: relative;
  display: inline-block;
  transition: all .5s;
}
#heart:hover{
  transform: scale(1.5);
}
#heart > .bottom{
  width:50px;
  height:50px;
  background: red;
  transform: rotate(45deg);
}
#heart > .left{
  width:50px;
  height:50px;
  background: red;
  border-radius:50% 50% 0 0;
  position: absolute;
  bottom: 100%;
  left: 100%;
  transform: rotate(45deg) translateY(31px);
}
#heart > .right{
  width:50px;
  height:50px;
  background: red;
  border-radius:50% 0 0 50%;
  position: absolute;
  bottom: 100%;
  right: 100%;
  transform: rotate(45deg) translateX(31px);
}

使用animation实现跳动的心

image.png
css代码

*{
  margin: 0;
  padding:0;
  box-sizing:border-box;
}
#heart{
  margin: 100px;
  position: relative;
  display: inline-block;
  animation: heart 500ms infinite alternate;
}
@keyframes heart {
  0%{
    transform: scale(1.0);
  }
  100%{
    transform: scale(1.5);
  }
}
#heart > .bottom{
  width:50px;
  height:50px;
  background: red;
  transform: rotate(45deg);
}
#heart > .left{
  width:50px;
  height:50px;
  background: red;
  border-radius:50% 50% 0 0;
  position: absolute;
  bottom: 100%;
  left: 100%;
  transform: rotate(45deg) translateY(31px);
}
#heart > .right{
  width:50px;
  height:50px;
  background: red;
  border-radius:50% 0 0 50%;
  position: absolute;
  bottom: 100%;
  right: 100%;
  transform: rotate(45deg) translateX(31px);
}

1、如何让一个元素变成圆形?

    border-radius:50% 50% 50%** 50%**; 

此时元素边框就是圆形,但你心里要把它当成方形对待。

评论