一行代码实现display"过渡动画"原理
时间:2022-07-24
本文章向大家介绍一行代码实现display"过渡动画"原理,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
写本文的起因
- 上篇文章,提到如何让display出现过渡动画,却没有仔细介绍原理。
- 为了更好的让想学习的人深入理解于是加班加点写下了这篇“短文”,我想以后还是以短文为主,不然大家看起来太累
正式开始
- 初始化界面
<!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>
#app {
width: 200px;
height: 200px;
background-color: red;
display: none;
transition: all 1s;
}
</style>
</head>
<body>
<div id="app">
</div>
<button id="test">测试</button>
</body>
</html>
- 此时我将app的display初始化为none,并且写入脚本文件
<style>
#app {
width: 200px;
height: 200px;
background-color: red;
display: none;
}
</style>
。。。
<script>
test.onclick = function () {
const app = document.querySelector('#app')
console.log(app, 'app')
app.style.transform = "translateX(200px)"
app.style.display = "block"
}
</script>
- 初始化界面变成了这样:
- 此时,我点击测试按钮
- 并没有出现动画,非常生硬的出来了,有一些场景我又要性能,比如初始化不渲染,但是当它出现又要有动画的时候,就有可能使用这行代码
test.onclick = function () {
const app = document.querySelector('#app')
console.log(app, 'app')
app.style.display = "block"
const height = app.offsetHeight
app.style.transform = "translateX(200px)"
}
- 当我加入const height = app.offsetHeight这行代码的时候,再点击测试按钮,display切换就顺带出来了“动画”,有了过度效果
- 为什么会出现动画了呢? 因为我读取dom的这些特殊属性时,浏览器就会强制清空渲染队列一次,让我拿到最新的值。也就是说读取的时候,其实已经是display为"block"了,因此。我们出现了过渡动画
效果如下所示:
出现“过渡动画”
是什么情况?
- 其实
display
是不能出现动画的,所以标题+了引号
- 怎么才能有过渡?
- 有数字的变化,例如透明度,从
0-1
. - 初始化有渲染展示的
- 在
transition
里面包含的属性 - ...等 大家可以补充
- 有数字的变化,例如透明度,从
为什么加了一行代码后,就能出现动画了?
- 大家在写现代前端框架,遇到最多的问题就是渲染的时期不确定的问题。
- 例如
vue
里面的nextTick
实现,有一个优雅降级的实现。它在mounted
生命周期函数里面去获取dom
节点时候,经常获取不到或者获取不到完整渲染的dom
节点。(我很久没有使用vue
了,有问题可以补充),为什么? - 像现在数据驱动的框架,只要数据改变了,对应逻辑绑定了数据的
dom
节点按道理应该更新,可是更新时机是我们无法确定的,因为这中间有中间层,比如存在diff
算法计算过程,可能存在队列,因为当你频繁修改数据的时候,框架本身要做优化,合并一段时间的数据更新再去真正更新dom
,等这些事情都做完了,才能去更新dom
节点,然后我们才能看到最新数据对应的节点 - 当我们真的要去更新
dom
节点的时候,也存在一个队列。这个就是浏览器的渲染队列
- 例如
---
- 如果你无法理解我上面说的,可以看我之前手写
React
系列文章中的setState
异步队列实现
浏览器的渲染队列
- 什么时候最能体现这个队列的作用?
- 频繁直接操作
dom
时候,例如for
循环里面频繁操作dom
,这个时候浏览器就会优化我们的操作,合并一部分操作一次性执行 - 渲染队列跟
display
的关联
- 频繁直接操作
<script>
test.onclick = function () {
const app = document.querySelector('#app')
console.log(app, 'app')
app.style.display = "block"
const height = app.offsetHeight
app.style.transform = "translateX(200px)"
}
</script>
- 当我们执行了
app.style.display = "block"
这行代码时候,dom
节点此时并没有更新,js
解析引擎是聪明的,它发现你后面马上有代码要修改dom
节点,会先存入队列中集中一次性操作 - 当我们执行了
app.offsetHeight
这行代码时候,发现我们需要读取dom
节点的属性,浏览器害怕现在队列中没有执行的操作会让你读取到不正确的值引发BUG
,于是就会清空渲染队列并且执行,让你拿到最精确/新的
值
- 当你请求向浏览器请求一些
style
信息的时候,就会让浏览器flush
队列,比如:offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop/Left/Width/Height
clientTop/Left/Width/Height
width,height
- 当你请求上面的一些属性的时候,浏览器为了给你最精确的值,需要
flush
队列, - 因为队列中可能会有影响到这些值的操作。即使你获取元素的布局和样式信息跟最近发生或改变的布局信息无关,
- 浏览器都会强行刷新渲染队列。
清空渲染队列后
- 当读取
offsetHeight
属性后,我们清空了渲染队列,那么此时dom
重新渲染完成后,此时display
已经是block
了。而且展示在界面上面了,我们再操作dom
属性就会出现过渡动画了。
最后
- 纸上得来终觉浅,多实践、多思考是走向更高级别必经之路,想要看我之前手写源码文章的,我的gitHub源码地址是:
https://github.com/JinJieTan/Peter-
,记得Star
哦
- linux下文件加密操作记录
- python的with语句,超级强大
- “AS3.0高级动画编程”学习:第二章转向行为(上)
- Linux下性能调试工具-top和sar运维笔记
- Apache+wsgi+flask部署
- “勒索病毒”到底会勒索啥,尽可以做到让全球对之恐惧无奈!
- 解决win10 关键错误开始菜单和cortana无法工作 的问题(转-真的成功了)
- “AS3.0高级动画编程”学习:第二章转向行为(下)
- windows系统中eclipse C开发环境的架设
- 5个酷毙的Python工具
- ”盒模型“之如何防止边框和内边距把元素撑开
- excel中的不同类型图表叠加
- 这几天遇到的关于IE6/sql2008/win2003的奇怪bug
- 基于Web的工作流管理系统的设计与实现
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 代码审计-.NET下的序列化与反序列化(BinaryFormatter)
- 深入探讨 JavaScript 逻辑赋值运算符
- Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
- 谈谈volatile
- 【V-REP自学笔记(八)】控制youBot抓取和移动物体
- Gson 简单使用姿势小结
- 【SpringBoot WebFlux 系列】WebFlux 之 Path 参数解析与 url 映射
- 「推荐」阿里开源的分布式事务框架 Seata
- BeanDefinition元信息:除了Bean名称和类名,还有哪些Bean元信息值得关注?
- 【SpringBoot WebFlux 系列】 header 参数解析
- MySQL为什么还有kill不掉的语句?
- 【SpringBoot DB 系列】h2databse 集成示例 demo
- 在grant语句之后要跟着flush privileges吗?
- Python实现数据写入 Excel 的三种模块!
- redis的两种持久化的机制,你真的了解么?