CSS3新增的语法(三)【2D,3D,过渡,动画】
CSS3新增的语法(三)【2D,3D,过渡,动画】
- 10.2D变换
- 10.1. 2D位移
- 10.2. 2D缩放
- 10.3. 2D旋转
- 10.4. 2D扭曲(了解)
- 10.5. 多重变换
- 10.6. 变换原点
- 11. 3D变换
- 11.1. 开启3D空间
- 11.2. 设置景深
- 11.3. 透视点位置
- 11.4. 3D 位移
- 11.5. 3D 旋转
- 11.6. 3D 缩放
- 11.7. 多重变换
- 11.8. 背部可见性
- 12. 过渡
- 12.1. transition-property
- 12.2. transition-duration
- 12.3. transition-delay
- 12.4. transition-timing-function
- 12.5. transition 复合属性
- 13. 动画
- 13.1. 什么是帧
- 13.2. 什么是关键帧
- 13.3. 动画的基本使用
- 13.4. 动画的其他属性
- 13.5. 动画复合属性
10.2D变换
10.1. 2D位移
2D 位移可以改变元素的位置,具体使用方式如下:
- 先给元素添加 转换属性 transform;
- 编写 transform 的具体值,相关可选值如下:
值 | 含义 |
---|---|
translateX | 设置水平方向位移,需指定长度值;若指定的是百分比,是参考自身宽度的百分比。 |
translateY | 设置垂直方向位移,需指定长度值;若指定的是百分比,是参考自身高度的百分比。 |
translate | 一个值代表水平方向,两个值代表:水平和垂直方向。 |
- 注意点:
- 位移与相对定位很相似,都不脱离文档流,不会影响到其它元素。
- 与相对定位的区别:相对定位的百分比值,参考的是其父元素;位移的百分比值,参考的是 其自身。
- 浏览器针对位移有优化,与定位相比,浏览器处理位移的效率更高。
- transform 可以链式编写,例如:
transform: translateX(30px) translateY(40px);- 位移对行内元素无效。
- 位移配合定位,可实现元素水平垂直居中
.box {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%); }
10.2. 2D缩放
2D 缩放是指:让元素放大或缩小,具体使用方式如下:
- 先给元素添加 转换属性 transform;
- 编写 transform 的具体值,相关可选值如下:
值 | 含义 |
---|---|
scaleX | 设置水平方向的缩放比例,值为一个数字, 1 表示不缩放,大于 1 放大,小于 1 缩小。 |
scaleY | 设置垂直方向的缩放比例,值为一个数字, 1 表示不缩放,大于 1 放大,小于 1 缩小。 |
scale | 同时设置水平方向、垂直方向的缩放比例,一个值代表同时设置水平和垂直缩放;两个值分别代表:水平缩放、垂直缩放。 |
- 注意点:
- scale 的值,是支持写负数的,但几乎不用,因为容易让人产生误解。
- 借助缩放,可实现小于 12px 的文字。
10.3. 2D旋转
2D 旋转是指:让元素在二维平面内,顺时针旋转或逆时针旋转,具体使用方式如下:
- 先给元素添加 转换属性 transform;
2.编写 transform 的具体值,相关可选值如下:
值 | 含义 |
---|---|
rotate | 设置旋转角度,需指定一个角度值( deg ),正值顺时针,负值逆时针。 |
注意: rotateZ(20deg) 相当于 rotate(20deg) ,当然到了 3D 变换的时候,还能写: rotate(x,x,x)
10.4. 2D扭曲(了解)
2D 扭曲是指:让元素在二维平面内被“拉扯”,进而“走形”,实际开发几乎不用,了解即可,具体使用方
式如下:
- 先给元素添加 转换属性 transform;
- 编写 transform 的具体值,相关可选值如下:
10.5. 多重变换
多个变换,可以同时使用一个 transform 来编写。
transform: translate(-50%, -50%) rotate(45deg);
注意点:多重变换时,建议最后旋转。(旋转后的坐标原点会变)
10.6. 变换原点
- 元素变换时,默认的原点是元素的中心,使用 transform-origin 可以设置变换的原点。
- 修改变换原点对位移没有影响, 对旋转和缩放会产生影响。
- 如果提供两个值,第一个用于横坐标,第二个用于纵坐标。
- 如果只提供一个,若是像素值,表示横坐标,纵坐标取 50% ;若是关键词,则另一个坐标取 50%
- transform-origin: 50% 50% , 变换原点在元素的中心位置,百分比是相对于自 身。—— 默认值
- transform-origin: left top ,变换原点在元素的左上角 。
- transform-origin: 50px 50px , 变换原点距离元素左上角 50px 50px 的位置。
- transform-origin: 0 ,只写一个值的时候,第二个值默认为 50% 。
11. 3D变换
11.1. 开启3D空间
重要原则:元素进行 3D 变换的首要操作:父元素必须开启 3D 空间!
-
使用 transform-style 开启 3D 空间,可选值如下:
- flat : 让子元素位于此元素的二维平面内( 2D 空间)—— 默认值
- preserve-3d : 让子元素位于此元素的三维空间内( 3D 空间)
11.2. 设置景深
何为景深?—— 指定观察者与 z=0 平面的距离,能让发生 3D 变换的元素,产生透视效果,看来更加立体。
使用 perspective 设置景深,可选值如下:
- none : 不指定透视 ——(默认值)
- 长度值 : 指定观察者距离 z=0 平面的距离,不允许负值。
注意: perspective 设置给发生 3D 变换元素的父元素!
11.3. 透视点位置
所谓透视点位置,就是观察者位置;默认的透视点在元素的中心。
使用 perspective-origin 设置观察者位置(透视点的位置),例如:
/* 相对坐标轴往右偏移400px, 往下偏移300px(相当于人蹲下300像素,然后向右移动400像素看元素)*/
perspective-origin: 400px 300px;
注意:通常情况下,我们不需要调整透视点位置。
11.4. 3D 位移
3D 位移是在 2D 位移的基础上,可以让元素沿 z 轴位移,具体使用方式如下:
- 先给元素添加 转换属性 transform;
- 编写 transform 的具体值, 3D 相关可选值如下:
值 | 含义 |
---|---|
translateZ | 设置 z 轴位移,需指定长度值,正值向屏幕外,负值向屏幕里,且不能写百分比。 |
translate3d | 第1个参数对应 x 轴,第2个参数对应 y 轴,第3个参数对应 z 轴,且均不能省略。 |
11.5. 3D 旋转
3D 旋转是在 2D 旋转的基础上,可以让元素沿 x 轴和 y 轴旋转,具体使用方式如下:
- 先给元素添加 转换属性 transform;
- 编写 transform 的具体值, 3D 相关可选值如下:
11.6. 3D 缩放
3D 缩放是在 2D 缩放的基础上,可以让元素沿 z 轴缩放,具体使用方式如下:
- 先给元素添加 转换属性 transform;
- 编写 transform 的具体值, 3D 相关可选值如下:
值 | 含义 |
---|---|
scaleZ | 设置 z 轴方向的缩放比例,值为一个数字, 1 表示不缩放,大于 1 放大,小于 1 缩小。(会影响景深) |
scale3d | 第1个参数对应 x 轴,第2个参数对应 y 轴,第3个参数对应 z 轴,参数不允许省略。 |
11.7. 多重变换
多个变换,可以同时使用一个 transform 来编写。
transform: translateZ(100px) scaleZ(3) rotateY(40deg);
注意点:多重变换时,建议最后旋转。
11.8. 背部可见性
使用 backface-visibility 指定元素背面,在面向用户时是否可见,常用值如下:
- visible : 指定元素背面可见,允许显示正面的镜像。—— 默认值
- hidden : 指定元素背面不可见
注意: backface-visibility 需要加在发生 3D 变换元素的自身上。
12. 过渡
过渡可以在不使用 Flash 动画,不使用 JavaScript 的情况下,让元素从一种样式,平滑过渡为另一 种样式。
12.1. transition-property
- 作用:定义哪个属性需要过渡,只有在该属性中定义的属性(比如宽、高、颜色等)才会以有过渡 效果。
- 常用值:
- none :不过渡任何属性。
- all :过渡所有能过渡的属性。
- 具体某个属性名 ,例如: width 、 heigth ,若有多个以逗号分隔。
注意:
- 不是所有的属性都能过渡,值为数字,或者值能转为数字的属性,都支持过渡,否则不支持 过渡。
- 常见的支持过渡的属性有:颜色、长度值、百分比、 z-index 、 opacity 、 2D 变换属 性、 3D 变换属性、阴影。
12.2. transition-duration
- 作用:设置过渡的持续时间,即:一个状态过渡到另外一个状态耗时多久。
- 常用值:
- 0 :没有任何过渡时间 —— 默认值。
- s 或 ms :秒或毫秒。
- 列表 :
- 如果想让所有属性都持续一个时间,那就写一个值。
- 如果想让每个属性持续不同的时间那就写一个时间的列表。
transition-duration:1s,2s;(两个过渡方式时)
12.3. transition-delay
- 作用:指定开始过渡的延迟时间,单位: s 或 ms
12.4. transition-timing-function
- 作用:设置过渡的类型
- 常用值:
1. ease : 平滑过渡 —— 默认值
2. linear : 线性过渡
3. ease-in : 慢 → 快
4. ease-out : 快 → 慢
5. ease-in-out : 慢 → 快 → 慢
6. step-start : 等同于 steps(1, start)
7. step-end : 等同于 steps(1, end)
8. steps( integer,?) : 接受两个参数的步进函数。第一个参数必须为正整数,指定函数的
步数。第二个参数取值可以是 start 或 end ,指定每一步的值发生变化的时间点。第二个
参数默认值为 end 。
9. cubic-bezie ( number, number, number, number): 特定的贝塞尔曲线类型。
------ 在线制作贝赛尔曲线:https://cubic-bezier.com
12.5. transition 复合属性
如果设置了一个时间,表示 duration ;
如果设置了两个时间,第一是 duration ,第二个是 delay ;
其他值没有顺序要求。
transition:1s 1s linear all;
13. 动画
13.1. 什么是帧
一段动画,就是一段时间内连续播放 n 个画面。每一张画面,我们管它叫做“帧”。一定时间内连续快速播放若干个帧,就成了人眼中所看到的动画。同样时间内,播放的帧数越多,画面看起来越流 畅。
13.2. 什么是关键帧
关键帧指的是,在构成一段动画的若干帧中,起到决定性作用的 2-3 帧。
13.3. 动画的基本使用
- 第一步:定义关键帧(定义动画)
-
简单方式定义:
/*写法一*/@keyframes 动画名 {from {/*property1:value1*//*property2:value2*/}to {/*property1:value1*/}}
-
完整方式定义:
@keyframes testKey {0% {/*property1:value1*/}20% {/*property1:value1*/}40% {/*property1:value1*/}60% {/*property1:value1*/}80% {/*property1:value1*/}100% {/*property1:value1*/} }
-
- 第二步:给元素应用动画,用到的属性如下:
- animation-name :给元素指定具体的动画(具体的关键帧)
- animation-duration :设置动画所需时间
- animation-delay :设置动画延迟
box {/* 指定动画 */animation-name: testKey;/* 设置动画所需时间 */animation-duration: 5s;/* 设置动画延迟 */animation-delay: 0.5s;}
13.4. 动画的其他属性
-
animation-timing-function ,设置动画的类型,常用值如下:
- ease : 平滑动画 —— 默认值
- linear : 线性过渡
- ease-in : 慢 → 快
- ease-out : 快 → 慢
- ease-in-out : 慢 → 快 → 慢
- step-start : 等同于 steps(1, start)
- step-end : 等同于 steps(1, end)
- steps( integer,?) : 接受两个参数的步进函数。第一个参数必须为正整数,指定
函数的步数。第二个参数取值可以是 start 或 end ,指定每一步的值发生变化的时间
点。第二个参数默认值为 end 。 - cubic-bezie ( number, number, number, number): 特定的贝塞尔曲线类型。
-
animation-iteration-count ,指定动画的播放次数,常用值如下:
- number :动画循环次数
- infinite : 无限循环
-
animation-direction ,指定动画方向,常用值如下:
- normal : 正常方向 (默认)
- reverse : 反方向运行
- alternate : 动画先正常运行再反方向运行,并持续交替运行
- alternate-reverse : 动画先反运行再正方向运行,并持续交替运行
-
animation-fill-mode ,设置动画之外的状态
- forwards : 设置对象状态为动画结束时的状态
- backwards : 设置对象状态为动画开始时的状态
-
animation-play-state ,设置动画的播放状态,常用值如下:
- running : 运动 (默认)
- paused : 暂停
13.5. 动画复合属性
只设置一个时间表示 duration ,设置两个时间分别是: duration 和 delay ,其他属性没有数量和 顺序要求。
.inner {animation: atguigu 3s 0.5s linear 2 alternate-reverse forwards;
}
备注: animation-play-state 一般单独使用。
相关文章:
CSS3新增的语法(三)【2D,3D,过渡,动画】
CSS3新增的语法(三)【2D,3D,过渡,动画】 10.2D变换10.1. 2D位移10.2. 2D缩放10.3. 2D旋转10.4. 2D扭曲(了解)10.5. 多重变换10.6. 变换原点 11. 3D变换11.1. 开启3D空间11.2. 设置景深11.3. 透视点位置11.4. 3D 位移11…...
Flutter应用在苹果商店上架前的准备工作与注意事项
引言 🚀 Flutter作为一种跨平台的移动应用程序开发框架,为开发者提供了便利,使他们能够通过单一的代码库构建出高性能、高保真度的应用程序,同时支持Android和iOS两个平台。然而,完成Flutter应用程序的开发只是第一步…...
如何开启MySQL的binlog日志
1.启用远程连接: 如果你想要允许远程主机连接到MySQL服务器,需要进行以下步骤: 确保MySQL服务器的防火墙允许远程连接的流量通过。在MySQL服务器上,编辑MySQL配置文件(一般是my.cnf),找到bind-…...
设计模式|状态机模式(State Machine Pattern)
文章目录 结构使用步骤示例使用状态机的场景常见面试题 状态机模式(State Machine Pattern)是一种用于描述对象的行为软件设计模式,属于行为型设计模式。在状态机模式中,对象的行为取决于其内部状态,并且在不同的状态下…...
Django源码之路由的本质(上)——逐步剖析底层执行流程
目录 1. 前言 2. 路由定义 3. 路由定义整体源码分析 3.1 partial实现path函数调用 3.2 图解_path函数 3.3 最终 4.URLPattern和Pattern的简单解析 5. 小结 1. 前言 在学习Django框架的时候,我们大多时候都只会使用如何去开发项目,对其实现流程并…...
基于深度学习的植物叶片病毒识别系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)
摘要:本文深入研究了基于YOLOv8/v7/v6/v5的植物叶片病毒识别系统,核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法,进行性能指标对比;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码,及基于Strea…...
Native Instruments Kontakt 7 for Mac v7.9.0 专业音频采样
Native Instruments Kontakt 7是一款强大的软件采样器,它允许用户从各种来源采样音频并进行编辑和处理。它包含大量预设采样库,包括乐器、合成器、鼓组和声音效果等。此外,Kontakt 7还允许用户创建自己的采样库,以便根据自己的需要…...
yolov8训练流程
训练代码 from ultralytics import YOLO# Load a model model YOLO(yolov8n.yaml) # build a new model from YAML model YOLO(yolov8n.pt) # load a pretrained model (recommended for training) model YOLO(yolov8n.yaml).load(yolov8n.pt) # build from YAML and tr…...
Java基础学习: Forest - 极简 HTTP 调用 API 框架
文章目录 一、介绍参考: 一、介绍 Forest是一个开源的Java HTTP客户端框架,专注于简化HTTP客户端的访问。它是一个高层的、极简的轻量级HTTP调用API框架,通过Java接口和注解的方式,将复杂的HTTP请求细节隐藏起来,使HT…...
Pandas Dataframe合并连接Join和merge 参数讲解
文章目录 函数与参数分析otheronhowlsuffix, rsuffix, suffixesleft_index, right_index 函数与参数分析 在pandas中主要有两个函数可以完成table之间的join Join的函数如下: DataFrame.join(other, onNone, how‘left’, lsuffix‘’, rsuffix‘’, sortFalse, v…...
ABC318 F - Octopus
解题思路 对于每个宝藏维护个区间,答案一定在这些区间中对于每个区间的端点由小到大排序对于每个点进行判断,若当前位置合法,则该点一定为一个右端点则该点到前一个端点之间均为合法点若前一个点不合法,则一定是某一个区间限制的…...
Docker实战教程 第3章 Dockerfile
4-2 通过dockerfile制作镜像 需求 制作一个具有ping ip ifconfig vim 这些命令工具的一个nginx镜像,通过dockerfile完成STEP1 : 写一个Dockerfile FROM nginx # 基于一个基础镜像 RUN lsstep2 docker build . -f 指定使用的dockerfile来生成镜像-t 指定镜像名…...
JSON在量化交易系统中的应用
JSON在量化交易系统中的应用场景 数据传输和存储:JSON可以将交易数据以结构化的方式进行编码,并将其转换为字符串进行传输和存储。这样可以方便地在不同的系统之间传递数据,并且可以保持数据的完整性和一致性。 API通信:量化交易…...
x-cmd-pkg | broot 是基于 Rust 开发的一个终端文件管理器
简介 broot 是基于 Rust 开发的一个终端文件管理器,它设计用于帮助用户在终端中更轻松地管理文件和目录,使用树状视图探索文件层次结构、操作文件、启动操作以及定义您自己的快捷方式。 同时它还集成了 ls, tree, find, grep, du, fzf 等工具的常用功能…...
设置asp.net core WebApi函数请求参数可空的两种方式
以下面定义的asp.net core WebApi函数为例,客户端发送申请时,默认三个参数均为必填项,不填会报错,如下图所示: [HttpGet] public string GetSpecifyValue(string param1,string param2,string param3) {return $"…...
Vue.js组件精讲 开篇:Vue.js的精髓——组件
写在前面 Vue.js,无疑是当下最火热的前端框架 Almost,而 Vue.js 最精髓的,正是它的组件与组件化。写一个 Vue 工程,也就是在写一个个的组件。 业务场景是千变万化的,而不变的是 Vue.js 组件开发的核心思想和使用技巧…...
R语言中的常用数据结构
目录 R对象的基本类型 R对象的属性 R的数据结构 向量 矩阵 数组 列表 因子 缺失值NA 数据框 R的数据结构总结 R语言可以进行探索性数据分析,统计推断,回归分析,机器学习,数据产品开发 R对象的基本类型 R语言对象有五…...
基于Python的微博旅游情感分析、微博舆论可视化系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
机器学习的模型校准
背景知识 之前一直没了解过模型校准是什么东西,最近上班业务需要看了一下: 模型校准是指对分类模型进行修正以提高其概率预测的准确性。在分类模型中,预测结果通常以类别标签形式呈现(例如,0或1)…...
0.17元的4位数码管驱动芯片AiP650,支持键盘,还是无锡国家集成电路设计中心某公司的
推荐原因:便宜的4位数码管驱动芯片 只要0.17元,香吗?X背景的哦。 2 线串口共阴极 8 段 4 位 LED 驱动控制/7*4 位键盘扫描专用电路 AIP650参考电路图 AIP650引脚定义...
【C++】编程规范之内存规则
在高质量编程中,内存管理是一个至关重要的方面。主要有以下原则: 内存分配后需要检查是否成功:内存分配可能会失败,特别是在内存紧张的情况下。因此,在分配内存后,应该检查分配是否成功。 int* ptr new …...
并发编程之线程池的应用以及一些小细节的详细解析
线程池在实际中的使用 实际开发中,最常用主要还是利用ThreadPoolExecutor自定义线程池,可以给出一些关键的参数来自定义。 在下面的代码中可以看到,该线程池的最大并行线程数是5,线程等候区(阻塞队列)是3,即…...
基于JSP的农产品供销服务系统
背景 互联网的迅猛扩张彻底革新了全球各类组织的运营模式。自20世纪90年代起,中国的政府机关和各类企业便开始探索利用网络系统来处理管理事务。然而,早期的网络覆盖范围有限、用户接受度不高、互联网相关法律法规不完善以及技术开发不够成熟等因素&…...
redis之主从复制、哨兵模式
一 redis群集有三种模式 主从复制: 主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。 主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。 缺陷: 故障恢复无法自动化&…...
【随笔】Git 基础篇 -- 分支与合并 git rebase(十)
💌 所属专栏:【Git】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…...
图像识别技术在体育领域的应用
图像识别技术在体育领域的应用是一个充满创新和挑战的研究方向。随着计算机视觉和人工智能技术的快速发展,图像识别技术已经在体育领域展现出广泛的应用潜力和实际价值。以下是一些图像识别技术在体育领域的具体应用: 运动员表现分析: 图像识…...
【项目新功能开发篇】开发编码
作者介绍:本人笔名姑苏老陈,从事JAVA开发工作十多年了,带过大学刚毕业的实习生,也带过技术团队。最近有个朋友的表弟,马上要大学毕业了,想从事JAVA开发工作,但不知道从何处入手。于是࿰…...
软件设计原则:开闭原则
定义 开闭原则(Open-Closed Principle, OCP)是面向对象设计的基本原则之一,由 Bertrand Meyer 提出。它指出软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着软件应该设计成在不修改现有代…...
Python如何下载视频
大家好,今天我将为大家介绍如何使用Python来下载视频。Python作为一门强大的编程语言,不仅可以用于数据分析、机器学习等领域,还能用于网络爬虫和视频下载等任务。下面我将详细介绍如何使用Python来下载视频。 首先,我们需要明确…...
使用虚拟引擎为AR体验提供动力
Powering AR Experiences with Unreal Engine 目录 1. 虚拟引擎概述 2. 虚拟引擎如何为AR体验提供动力 3. 虚拟引擎中AR体验的组成部分是什么? 4. 使用虚拟引擎创建AR体验 5. 虚拟引擎中AR的优化提示 6. 将互动性融入AR与虚拟引擎 7. 在AR中…...
做网站怎么这么贵/做整站优化
最近更新的博客 【新解法】华为OD机试 - 关联子串 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 停车场最大距离 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 任务调度 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试…...
功能型网站 设计/青岛网站排名公司
在看Thomas Kyte大师的《Oracle Database 9i/10g/11g编程艺术》的配置环境一节有一个login.sql脚本define _editorviset serveroutput on size 1000000set trimspool onset long 5000set linesize 100set pagesize 9999column plan_plus_exp format a80column global_name new_…...
如何做自己个人网站/兰州seo技术优化排名公司
sprintf是格式化字符串最常用的方式。vsprintf可以很方便的使用va_list,对应的宽字符版本就是vswprintf。在跨平台上使用vswprintf,于是噩梦开始了。支持最好的当然是windows,一点问题都没有。mac/ios上如果是宽字节的英文字符则是正常的,如果…...
网站建设与管理ppt课件百度云盘/百度竞价推广自己可以做吗
大家都有这样的经历: 打开VS--〉新建应用程序(FORM1)--〉往里面挪按钮--〉双击按钮--〉写代码 这看上去那么的自然,简单&#x…...
wordpress 调用avatar/宁波seo优化流程
引言 前几期的评测中,我们对比了Kafka和RocketMQ的吞吐量和稳定性,本期我们要引入一个新的评测标准——软件可靠性。 何为“可靠性”?先看下面这种情况:有A,B两辆越野汽车,在城市的周边地区均能很好应对泥泞…...
湖北网站建设服务/网络营销与市场营销的区别
https://blog.csdn.net/java_dotar_01/article/details/76942563 https://blog.csdn.net/jiuduan2009/article/details/51737004转载于:https://www.cnblogs.com/wangshaowei/p/10272467.html...