2020-12-05 CSS定位 + 动画

1. CSS 定位

(1) div分层

  • 布局是屏幕上面的(x y轴),定位是垂直于屏幕的(z轴)
  • 内联子元素 > 浮动元素 > 块级元素 > border > background
z轴demo.png

(2) position

  • static 当前元素在文档流中(默认值)
  • relative 当前元素在文档流中,所占位置不变,但显示位置相对偏移(相对于自己),用来给absolute元素做父级元素
  • absolute 绝对定位必须要有父元素,必须知道基准于哪个元素,父级元素加 position: relative;(它会找祖先元素中最近的一个不是static定位的元素,可以相对于"爷爷元素"定位)
    Example: 鼠标提示
button {
  position: relative;
}
button span {
  position: absolute;
  white-space: nowrap; /*不换行*/
  bottom: calc(100% + 2px); /*在100%的基础上再+2px*/
  left: 50%; /*从基准元素50%位置开始*/
  transform: translateX(-50%); /*相对基准元素居中*/
}
button span { 
  display: none;
}
/*鼠标悬浮button位置显示span*/
button:hover span{
  display: inline-block;
}
  • fixed 相对于视口定位(页面可视区域)-> 用于锁死广告位置
    ps.
    a. 如果父元素有transform属性,fixed定位将产生bug
    b. 手机页面最好不用fixed,很多bug
  • sticky 原位置文档流,快要超出可视范围时粘住顶端,但兼容性很差 -> 适合导航栏

(3) 层叠上下文

  • 当position为非static时,其成为定位元素,根据下图z-index确定位置,正数在内联子元素上,负数在background下


    position与div分层的关联.png
  • z-index 默认值为auto,auto计算出来的值为0,z-index越大越在上层 (但如果其所在父元素的z-index比另外元素的父元素z-index低,则按父元素z-index大小层叠),不要写 z-index: 9999; 要学会管理z-index

    层叠上下文.png

  • 创建层叠上下文的属性:MDN 文档
    需要记忆:z-index/flex/opacity/transform
    【补充知识】透明度background alpha和opacity的区别:
    background影响元素背景,opacity影响整个元素
    csdn 解释
    1、首先先看要比较的两个元素是否处于同一个层叠上下文中: 1.1如果是,谁的层叠等级大,谁在上面(怎么判断层叠等级大小呢?——看“层叠顺序”图)。 1.2如果两个元素不在统一层叠上下文中,请先比较他们所处的层叠上下文的层叠等级。 2、当两个元素层叠等级相同、层叠顺序相同时,在DOM结构中后面的元素层叠等级在前面元素之上。

  • 负z-index可能因父元素产生层叠上下文的属性而失效


2. CSS 动画

2.1 先导

(1) 概念

  • 每个静止的画面都叫帧
  • 播放速度:每秒24帧(影视)或每秒30帧(游戏)

(2) 简单例子 - 矩形框的移动

  • 改变left
#demo{
  width: 100px;
  height: 100px;
  border: 1px solid red;
  position: relative;
  left: 0;
}
var n = 1
/* 计时器 */
var id = setInterval(() => {
  console.log(n)
  if (n <= 100) {
    demo.style.left = n / 100 * 300 + 'px'
    n = n + 1
  }else{
    clearInterval(id) /*停止计时器*/
  }
}, 1000 / 30) /*30帧,此处为间隔的时间*/
  • 用transform渲染,性能更高,不需要repaint
#demo{
  width: 100px;
  height: 100px;
  border: 1px solid red;
  transition: all 1s linear;
}

#demo.end{
  transform: translateX(300px);
}
setTimeout(()=>{
  demo.classList.add('end') /*加上end类*/
},0)

(3) 查看渲染性能

开发者工具 -> Console -> Rendering -> 勾选Paint flashing


查看渲染性能.png

(4) 浏览器渲染过程

浏览器渲染过程.png

(5) 一般用JS来更新样式

  • div.style.background = 'red' 改变背景色
  • div.style.display = 'none' 使元素消失
  • div.classList.add = 'red' 给元素增加类(推荐,比改变style更快 每个类可包含多个style)
  • div.remove() 删除节点

(6) 三种更新方式

  • 查看css不同属性触发的渲染过程

    三种更新方式.png

  • 三步重新进行,Layout > Paint > Compose
    如div.remove()

  • 跳过Layout,进行Paint > Compose
    如改变背景色

  • 跳过Layout和Paint,只进行Compose
    如transform

(7) CSS 动画优化

  • Google全文
  • JS优化:使用 requestAnimationFrame 代替 setTimeout 或 setInterval
  • CSS优化:使用 will-change 或 translate

2.2 transform

(1) transform 完整语法:MDN

(2) 常用功能

  • 设置动画的时间:transition: all 1s;
  • 组合效果用空格隔开:transform: effect1 effect2;
A. translate 位移(X Y Z 轴), 参数为长度或百分数(基于元素自己宽度的百分比)
  • translateX(Npx)
  • translateY(Npx)
  • translateZ(Npx)

【开启Z轴需要增加视点】在父元素添加属性:

.wrapper{
  perspective: 1000px; /*视点设置为正中心1000像素*/
}
  • 简写
    a. 移动X, Y轴:translate(N1px, N2px)
    b. 移动X, Y, Z轴:translate3d(N1px, N2px, N3px)
  • 通常用translate(-50%, -50%)使子元素居中
    transform: translate(-50%, -50%); <=> transform: translateX(-50%) translateY(-50%);
.wrapper {
  position: relative;
}
#demo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); 
}
B. scale 缩放

-> 用的较少,容易出现模糊

  • scale(倍数1, 倍数2)
  • scaleX(倍数)
  • scaleY(倍数)
C. rotate 旋转
  • rotate(Ndeg) deg度数(正数顺时针)
  • rotateX(Ndeg) 沿X轴旋转
  • rotateY(Ndeg) 沿Y轴旋转
  • rotate3d 很复杂
D. skew 倾斜变形

-> 矩形变平行四边形

  • skewX(Ndeg) 沿X轴倾斜
  • skewY(Ndeg) 沿Y轴倾斜

(3) 实践:跳动的心

  • 思路先做心形,再放动画
  • 心形可由一个旋转45度的正方形和两个圆组成
  • http://js.jirengu.com/yecib/1/edit?html,css,output
* {margin: 0; padding:0; box-sizing: border-box;}
#heart {
  position: relative;
  display: inline-block;
  transition: all .5s; /*0.5s可以写成.5s*/
}
# heart:hover {
  transform: scale(1.5);
}
#heart > bottom {
  width: 50px;
  height: 50px;
  background: red;
  position: absolute;
  transform: rotate(45deg);
}
#heart > left {
  width: 50px;
  height: 50px;
  background: red;
  border-radius: 50% 0 0 50%; /*做两个圆角*/
  position: absolute;
  bottom: 100%;
  right: 100%;
  transform: rotate(45deg) translateX(31px); /*向右下移动*/
}
#heart > right {
  width: 50px;
  height: 50px;
  background: red;
  border-radius: 50% 50% 0 0;
  position: absolute;
  bottom: 100%;
  left: 100%;
  transform: rotate(45deg) translateY(31px);
}


2.3 transition

  • MDN文档

(1) 作用:添加中间帧

  • transition: width 1s; 如果width变化,则添加1秒过渡动画

(2) 语法: transition: 属性名 时长 过渡方式 延迟;

A. 属性名
  • all 表所有属性
B. 时长:动画持续时间
  • 时间单位可以为ms或s
C. 过渡方式
  • linear 匀速变化
  • ease 先快后慢
  • ease-in 淡入
  • ease-out 淡出
  • ease-in-out 淡入淡出
D. 延迟:过多久开始动画
  • 时间单位可以为ms或s

(3) Example: 元素慢慢消失,调透明度

或调visibility,从visible => hidden

# demo {
  width: 100px;
  height: 100px;
  border: 1px solid red;
  transition: all 1s;
  opacity: 1;
}
/*这里也可用hover演示*/
# demo.end {
  width: 200px;
  height: 200px;
  opacity: 0;
}
x.onlick = () => {
  demo.classList.add('end')
  setTimeout(() => { demo.remove() }, 1000) /*定时器 1s以后删除元素,防止其占位置*/
}

(4) 有中间帧情况需要设置多个类进行多次transform

.a ==> transform ==> .b ==> transform ==> .c

x.onlick = () => {
  demo.classList.add('b')
  setTimeout(() => { 
    demo.classList.remove('b') 
    demo.classList.add('c')
  }, 1000)
}


2.4 animation

  • MDN文档

(1) 用法

  • 将关键帧写入keyframes里(注意下一个关键帧transform效果要叠加上一个关键帧效果实现连续的动画) => keyframes挂载在元素的一个类的属性animation中并设置动画时间 => 通过js挂载类启动
  • keyframes也可以写成from{ } to{ }的形式
  • animation加上forwards可以停滞在最后一帧:animation: bubble 1.0s forwards;

Example:

demo.a {
  animation: xxx 1.5s; /*keyframes xxx已定义在下面*/
}
/*百分数表示动画进程百分比*/
@keyframs xxx {
  0% {
    transform: none;  
  }
  66% {
    transform: translateX(200px);
  }
  100% {
    /*叠加60%的effects*/
    transform: translateX(200px) translateY(200px); 
  }
}
button.onlick = () => {
  demo.classList.add('a')
}

(2) animation语法

animation语法.png

(3) 动画暂停与恢复

  • 设置元素的animationPlayState属性
/*暂停动画*/
button1.onlick = () => {
  demo.style.animationPlayState = 'paused'
}
/*恢复动画*/
button2.onlick = () => {
  demo.style.animationPlayState = 'running'
}

(4) 实践:使刚才的红心跳动

  • http://js.jirengu.com/yecib/2/edit?html,css,output
#heart {
  position: relative;
  animation: jump 800ms infinite alternate;
}
@keyframes jump { 
  from {transform: scale(1.0);}
  to{transform: scale(1.5);}
} 

你可能感兴趣的:(2020-12-05 CSS定位 + 动画)