一:浏览器渲染原理
- 根据HTML创建HTML树(DOM)
- 根据CSS创建CSS树(CSSOM)
- 合并两棵树创建RENDER TRee(渲染树)
- LAYOUT 布局<文档流、盒模型、计算大小和位置以及文字的颜色>
- PAINT 绘制<把边框的颜色、文字颜色、以及阴影画出来>
- COMPOSE 合成(根据层叠关系,进行展示画面)
二:更新样式
- 一般用JS更新样式
例如
div.stylr.background = 'red' div.style.display = 'none' div.classList.add('red') div.remove()删除节点
- 三种更新方式
- 第一种 , 全走
- div.remove()会触发当前消失,其他元素relayout
- 代码演示:js.jirengu.com/lexatetumi/…
- 第二种,跳过layout
- 改变背景颜色,直接repain+composite
- 代码演示:js.jirengu.com/jidam/1/edi…
- 第三种 ,跳过layout和pain
- 改变transform,只需composite
- 注意必须全屏查看效果,在iframe里看有问题
- 代码演示:js.jirengu.com/wusew/1/edi…
三:css动画优化
JS优化:使用requestAnimationFrame代替setTimeout或setlnterval CSS优化:使用will-change或translate
四:CSS动画的两种做法
4.1. transform
- 位移 translate
属性演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#demo {
width: 100px;
height: 200px;
border: 1px solid red;
margin: 50px;
}
#demo:hover {
transform: translateX(50px);
/* 向X轴移动50像素 */
transform: translateY(-50px);
/* 向Y轴移动-50像素 */
transform: translateZ(-200px);
/* 向Z轴移动-200像素 */
}
.wrapper {
perspective: 1000px;
/* 视觉大小为1000像素 */
/* perspective指定了观察者与 z=0 平面的距离,使具有三维位置变换的元素产生透视效果。 z>0 的三维元素比正常大,而 z<0 时则比正常小,大小程度由该属性的值决定 */
border: 1px solid black;
}
</style>
</head>
<body>
<div class="wrapper">
<div id="demo"></div>
</div>
</body>
</html>
- 缩放 scale 属性演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#demo {
height: 300px;
width: 300px;
border: 1px solid palevioletred;
margin: 50px;
}
#demo:hover {
transform: scaleX(1.5);
/* X轴缩放1.5倍 */
transform: scaleY(0.5);
/* Y轴缩放0.5倍 */
/* transform: scale(1.5, 0.5); */
/* 另一种写法 */
}
.wrapper {
perspective: 1000px;
border: 5px solid blueviolet;
}
</style>
</head>
<body>
<div class="wrapper">
<div id="demo"></div>
</div>
</body>
</html>
- 旋转 rotate 属性演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#demo {
height: 300px;
width: 300px;
border: 1px solid palevioletred;
margin: 150px;
}
#demo:hover {
transform: rotateX(45deg);
/* X轴旋转45度 */
transform: rotateY(90deg);
/* Y轴旋转90度 */
transform: rotateZ(30deg);
/* Z轴旋转30度 */
}
.wrapper {
perspective: 1000px;
border: 5px solid blueviolet;
}
</style>
</head>
<body>
<div class="wrapper">
<div id="demo"></div>
</div>
</body>
</html>
- 倾斜 skew 属性演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#demo {
height: 300px;
width: 300px;
border: 1px solid palevioletred;
margin: 150px;
}
#demo:hover {
/* transform: skewX(45deg); */
/* X轴倾斜45度 */
transform: skewY(45deg);
/* Y轴倾斜90度 */
}
.wrapper {
perspective: 1000px;
border: 5px solid blueviolet;
}
</style>
</head>
<body>
<div class="wrapper">
<div id="demo"></div>
</div>
</body>
</html>
transform属性全解链接:transform
五:transition
5.1. 属性名:宽度,高度,all(代表所有属性)
5.2 过渡方式 linear,ease,ease-in,ease-in,ease-out,ease-in-out等
liner:
ease:
ease-in:
ease-out:
ease-in-out:
注意:不可以过度的属性
- display:none==>black,display会直接消失 可以更改成visibility:visible==>hidden
- opacity:透明度可以过度但是过度以后虽然完全消失但是还是会占着位置
注意:
过渡必须有始有终,一般只有一次动画或者两次。
例如:hover和非hover状态的一个过度,出现了中间点该如何?
- 使用transform从a->b,再从b->到c
#demo{
width: 100px;
height: 100px;
border: 1px solid red;
margin: 50px;
transition: transform 1s linear;
}
#demo.b{
transform: translateX(200px);
}
#demo.c{
transform: translateX(200px) translateY(100px);
}
button.onclick = ()=>{
demo.classList.add('b')
setTimeout(()=>{
demo.classList.remove('b')
demo.classList.add('c')
},1000)
}
展示:[js.jirengu.com/jilofegesa/…
六:animation的具体用法
- 缩写语法 animation:时长/过渡方式/延迟/次数/方向/填充模式/是否暂停/动画名;
- 时长:1s or 1000ms
- 过渡方式: 与transition相似 有:linear等
- 次数:3或者2.4 或者infinite(无穷的)
- 方向:reverse alternate alternate-reverse(交替反向)
- 填充方式:none forwards backwards both
- 是否暂停:paused running
语法1:
语法2:
代码介绍:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
#demo{
width: 100px;
height: 100px;
border: 1px solid red;
margin: 50px;
}
#demo.start{
animation: xxx 2s ease 1s infinite alternate forwards;/*加上名字加上时间就可以,forward可以最后停在最后的位置 infinite无线循环*/
}
@keyframes xxx {
0% {
transform: none;
}
66.66%{
transform: translateX(200px);
}/*关键帧*/
80%{
transform: translateX(200px) translateY(100px);
}
100%{transform: translateX(200px) translateY(100px) translateX(100px);
}
}
</style>
</head>
<body>
<div class="wrapper">
<div id="demo"></div>
<button id=button>开始</button>
<button id=xxx>暂停</button>
<button id=yyy>继续</button>
</div>
</body>
</html>
代码效果展示: [js.jirengu.com/dezoroyuxe/…
跳动红心代码展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>red heart</title>
<style>
* {
box-sizing: border-box;
}
#box {
display: inline-block;
margin: 100px;
position: relative;
/* background-color: red; */
/* border: 1px solid palegreen; */
animation: .3s heart infinite alternate-reverse;
}
#box:hover {
transform: scale(1.2);
}
#box>.left {
width: 100px;
height: 100px;
/* border: palegreen 1px solid; */
background: purple;
transform: rotate(45deg) translateX(62px);
/* 旋转45度,向X轴移动31像素 */
position: absolute;
bottom: 100px;
left: -100px;
border-radius: 50% 0 0 50%;
}
#box>.right {
width: 100px;
height: 100px;
/* border: palegreen 1px solid; */
background: purple;
transform: rotate(45deg) translateY(62px);
/* 旋转45度,向Y轴移动31像素 */
position: absolute;
bottom: 100px;
right: -100px;
border-radius: 50% 50% 0 0;
}
#box .bottom {
background: purple;
width: 100px;
height: 100px;
transform: rotate(45deg);
}
#name {
position: absolute;
/* top: 50px; */
right: 230px;
bottom: 60px;
color: royalblue;
}
#box1 {
display: inline-block;
margin: 100px;
position: relative;
/* background-color: red; */
/* border: 1px solid palegreen; */
/* transition: all 1s; */
animation: 1s heart infinite alternate-reverse;
}
@keyframes heart {
0% {
transform: scale(1);
}
100% {
transform: scale(2);
}
}
/* #box1:hover {
transform: scale(1.2);
}
*/
#box1>.left1 {
width: 50px;
height: 50px;
/* border: palegreen 1px solid; */
background: red;
transform: rotate(45deg) translateX(31px);
/* 旋转45度,向X轴移动31像素 */
position: absolute;
bottom: 50px;
left: -50px;
border-radius: 50% 0 0 50%;
}
#box1>.right1 {
width: 50px;
height: 50px;
/* border: palegreen 1px solid; */
background: red;
transform: rotate(45deg) translateY(31px);
/* 旋转45度,向Y轴移动31像素 */
position: absolute;
bottom: 50px;
right: -50px;
border-radius: 50% 50% 0 0;
}
#box1 .bottom1 {
background: red;
width: 50px;
height: 50px;
transform: rotate(45deg);
}
#name1 {
position: absolute;
/* top: 50px; */
right: 230px;
bottom: 60px;
color: royalblue;
}
#box2 {
display: inline-block;
margin: 100px;
position: relative;
/* background-color: red; */
/* border: 1px solid palegreen; */
transition: all 1s;
}
#box2:hover {
transform: scale(1.2);
}
#box2>.left2 {
width: 50px;
height: 50px;
/* border: palegreen 1px solid; */
background: red;
transform: rotate(45deg) translateX(31px);
/* 旋转45度,向X轴移动31像素 */
position: absolute;
bottom: 50px;
left: -50px;
border-radius: 50% 0 0 50%;
}
#box2>.right2 {
width: 50px;
height: 50px;
/* border: palegreen 1px solid; */
background: red;
transform: rotate(45deg) translateY(31px);
/* 旋转45度,向Y轴移动31像素 */
position: absolute;
bottom: 50px;
right: -50px;
border-radius: 50% 50% 0 0;
}
#box2 .bottom2 {
background: red;
width: 50px;
height: 50px;
transform: rotate(45deg);
}
#box3 {
display: inline-block;
margin: 100px;
position: relative;
/* background-color: red; */
/* border: 1px solid palegreen; */
transition: all 1s;
}
#box3:hover {
transform: scale(1.2);
}
#box3>.left3 {
width: 50px;
height: 50px;
/* border: palegreen 1px solid; */
background: red;
transform: rotate(45deg) translateX(31px);
/* 旋转45度,向X轴移动31像素 */
position: absolute;
bottom: 50px;
left: -50px;
border-radius: 50% 0 0 50%;
}
#box3>.right3 {
width: 50px;
height: 50px;
/* border: palegreen 1px solid; */
background: red;
transform: rotate(45deg) translateY(31px);
/* 旋转45度,向Y轴移动31像素 */
position: absolute;
bottom: 50px;
right: -50px;
border-radius: 50% 50% 0 0;
}
#box3 .bottom3 {
background: red;
width: 50px;
height: 50px;
transform: rotate(45deg);
}
</style>
</head>
<body>
<div id="box">
<div class="left"></div>
<div class="right"></div>
<div class="bottom
</div>
</div>
<!-- <span id="name"></span> -->
<div id="box1">
<div class="left1"></div>
<div class="right1"></div>
<div class="bottom1">
</div>
</div>
<!-- <span id="name1"></span> -->
<div id="box2">
<div class="left2"></div>
<div class="right2"></div>
<div class="bottom2">
</div>
</div>
</body>
</html>