详解如何用 CSS3 完成 3D transform变换
Tips:阅读提示!!!
- 首先,本文针对的是3D transform变换的学习,所以你需要对 2D transform变换 有一定的了解
- 其次,需要说明的是,代码是一种需要自己不断实践的学科,建议各位在开始学习本篇文档的时候,先创建一个
html页面来边读边练,
相信这样,一定会给你留下一个非常直观且深刻的印象!
本文练习一些公共代码
鉴于本文贴了不少代码来演示,所有这里提前放一个所有演示的公共代码片段
// 公共DOM元素,后续均为此写样式表
// 舞台容器
<div class="stage">
// 变换元素
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
// 样式兼容的各个浏览器属性头,有需要的在各自代码中添加
// 下列测试代码使用Chorme运行
-webkit- /* Safari 和 Chrome */
-ms- /* IE */
-moz- /* Firefox */
-o- /* Opera */
实现3D变换的基础 -- 透视(perspective)
当我们步入CSS3动画殿堂之时,我们一般都会从一些简单动的东西开始学习,比如元素的位移,旋转,放大缩小之类的2D transform变换,
那么如何在一个2D的屏幕上实现3D的变换呢,这里我们就先需要有一个概念,就是 透视
从一个最简单的 透视 说起,我们小时候的数学课上,数学老师一定会给我们画一个立体正方形,能够在2D平面上看出3D效果就是 透视 的作用
用一张直观的图片来说明一下

透视的类型有以下几种

那么在CSS3中如何用代码实现透视呢?
- 主要是通过
perspective属性来实现定义透视距离 perspective属性定义3D元素距视图的距离,以像素计,该属性允许您改变3D元素查看3D元素的视图- 透视距离可以这么理解,如果你的显示器宽度是
1920px的分辨率,那么2000px的透视距离就近似于,从显示器平面开始,一个显示器宽度的距离 - 默认值是
0px,可以理解为初始位置 - 注意!!!当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身
- 它有两种写法,单个元素时候看似效果相同,但是多元素在同一个舞台上呈现时,就会出现问题了
- 第一种,是写在舞台元素上,定义
perspective属性 - 第二种,是配合
transform属性一起,例如:transform: perspective(600px) rotateY(45deg) - 参考下方示例,您可以在自己的demo中测试效果区别,你会发现第二种所有元素都是同一角度的旋转,
这是因为第一种透视点是.stage中央,第二种透视点是每一个.box中央
- 第一种,是写在舞台元素上,定义
// 第一种写法
.stage {
width: 100%;
height: 100%;
perspective: 1000px;
-webkit-perspective: 500px;
}
.stage .box {
width: 100px;
height: 100px;
margin: 100px 100px;
background-color: #55ffff;
display: inline-block;
transform: rotateY(65deg);
-webkit-transform: rotateY(65deg);
}
// 第二种写法
.stage {
width: 100%;
height: 100%;
}
.stage .box {
width: 100px;
height: 100px;
margin: 100px 100px;
background-color: #55ffff;
display: inline-block;
transform: perspective(1000px) rotateY(65deg);
-webkit-transform: perspective(1000px) rotateY(65deg);
}
透视基点位置属性(perspective-origin)
- 既然我我们有透视距离的概念,那么这个透视基点的意思就是,我们所看的舞台或者元素的中心
perspective(透视)属性必须和perspective-origin(透视基点)属性一同使用perspective-origin: x-axis y-axis,xy可以分别是这些值:- left
- right
- center
- length,像素
- %,百分比
- 举个不恰当的例子,透视基点类似看足球比赛中那个球的位置,因为所有人眼都会盯着场上的足球,你和球的距离理解为透视距离就好,当然这并不恰当,不要在意
- 该属性必须与
perspective属性一同使用,而且只影响3D转换元素,它可以定义在元素中,并且同perspective属性一样,定义在哪里影响哪里 - 默认值是
50% 50%,表示 xy 中心位置 - 下面我们利用一个示例来看看,你依旧可以通过修改demo中的参数,看到效果的变化
// 50% 50% 正好是变换元素的中心点,也是默认值
.stage {
width: 100%;
height: 100%;
perspective: 604px;
-webkit-perspective: 604px;
// 使用百分比
perspective-origin: 50% 50%;
-webkit-perspective-origin: 50% 50%;
// 使用像素
// perspective-origin: 200px 100px;
// -webkit-perspective-origin: 200px 100px;
// 使用位置
// perspective-origin: left center;
// -webkit-perspective-origin: left center;
// 也可以混用
// perspective-origin: 200px 10%;
// -webkit-perspective-origin: 200px 10%;
}
.stage .box {
width: 100px;
height: 100px;
margin: 100px 100px;
background-color: #55ffff;
display: inline-block;
transform: rotateY(65deg);
-webkit-transform: rotateY(65deg);
}
透视盲区
在我们进行3D变换的时候还会遇到透视盲区的问题,比如一个正方形,旋转45°之后,正好和你的视线完全平行,那么这个面你就看不到,这就是视觉盲区
你可以利用下方代码在自己的demo中查看一下效果
// 我的电脑分辨率是`1920*1080`,透视距离是`604px`
// 如果你看不到效果,可以尝试修改旋转角度或透视距离,找一下出现盲区的角度
.stage {
width: 100%;
height: 100%;
perspective: 604px;
-webkit-perspective: 604px
}
.stage .box {
width: 100px;
height: 100px;
margin: 100px 100px;
background-color: #55ffff;
display: inline-block;
transform: rotateY(65deg);
-webkit-transform: rotateY(65deg);
}
实现静态的3D变换 -- 转换(transform)
相信在2D变换的学习中对于transform属性一定不陌生了,它不仅可以进行2D变换,也可以进行3D变换,只不过需要借助上一个透视的属性,我们才可以在屏幕中看到变换的效果
先来说明一个三维坐标系的概念,通俗点来说,z轴对应垂直方向,x轴对应前后方向,y轴对应左右方向
后续我们所说的绕轴变化,你就可以参考这个图例,想象一下发生的变换

接下来我们来看看transform支持的变换类型,如果对此您有疑问,可以参考w3school的可测试教程:
- 2D类型
转换(位移)
translate(x,y)/translateX(x)/translateY(y)
缩放scale(x,y)/scaleX(x)/scaleY(y)
旋转rotate(angle)/rotateX(angle)/rotateY(angle)
倾斜skew(x-angle,y-angle)/skewX(angle)/skewY(angle)
matrix(),把所有 2D 变换方法组合为一个,可接受六个参数,matrix(scaleX(),skewY(),skewX(),scaleY(),translateX(),translateY()) - 3D类型
转换(位移)
translate3d(x,y,z)/translateZ(z),主要是垂直距离的位移
缩放scale3d(x,y,z)/scaleZ(z),同样是垂直距离的缩放
旋转rotate3d(x,y,z,angle)/rotateX(angle)/rotateY(angle)/rotateZ(angle)
rotateX/rotateY/rotateZ三种函数分别意思是绕着XYZ轴做旋转运动,angle参数为单位为deg的角度
rotate3d函数定义一个变换,它将元素围绕固定轴移动而不使其变形,运动量由指定的角度定义,
如果为正,运动将为顺时针,如果为负,则为逆时针,想要了解更多可以参考 这篇文档中的动态示例 理解
2D变换请参考 本文Tips中的链接 或百度教程,下面我们来详细看下实现静态3D变换的代码
.stage {
width: 100%;
height: 100%;
perspective: 500px;
-webkit-perspective: 500px;
perspective-origin: 50% 50%;
-webkit-perspective-origin: 50% 50%;
}
.stage .box {
width: 100px;
height: 100px;
margin: 100px 100px;
background-color: #55ffff;
display: inline-block;
// 这里表示绕Y轴做旋转65度的变换
transform: rotate3d(0, 1, 0, 65deg);
-webkit-transform: rotate3d(0, 1, 0, 65deg);
}
转换基点位置属性(transform-origin)
transform-origin属性允许您改变被转换元素的位置,2D转换元素能够改变元素xy轴,3D转换元素还能改变其z轴transform-origin: x-axis y-axis z-axis,这定义了视图被置于xyz轴的何处,z值只能是length,xy可以分别是这些值:- left
- right
- center
- length,像素
- %,百分比
transform-origin属性必须和transform属性一同使用- 默认值是
50% 50% 0,表示转换基点位于 xy 中心以及 z轴 0 的位置 - 下面我们利用一个示例来看看,你依旧可以通过修改demo中的参数,看到效果的变化
.stage {
width: 100%;
height: 100%;
perspective: 500px;
-webkit-perspective: 500px;
perspective-origin: 50% 50%;
-webkit-perspective-origin: 50% 50%;
}
.stage .box {
width: 100px;
height: 100px;
margin: 100px 100px;
background-color: #55ffff;
display: inline-block;
transform: rotate3d(0, 1, 0, 65deg);
-webkit-transform: rotate3d(0, 1, 0, 65deg);
// 表示旋转元素的基准点在 x 100px y 100px z -900px 位置
// 值类型自由使用,不做过多说明,参考上方透视基点属性
transform-origin: 100px 100px -900px;
-webkit-transform-origin: 100px 100px -900px;
}
转换如何呈现属性(transform-style)
transform-style属性规定如何在3D空间中呈现被嵌套的元素transform-style: flat | preserve-3d,flat表示子元素将不保留其3D位置,preserve-3d表示子元素保留其3D位置- 默认值是
flat,不保留3D位置 - 下面用一个不同于上面几个示例的示例来展示整个属性的效果,你可以在demo中修改几个属性来查看效果
<div class="stage">
<div class="box">
<div class="box-out">
<div class="box-in"></div>
</div>
</div>
</div>
.stage {
width: 100%;
height: 100%;
perspective: 1600px;
-webkit-perspective: 1600px;
}
.stage .box {
width: 400px;
height: 400px;
margin: 100px 100px;
background-color: #55ffff;
transform: rotate3d(0, 1, 0, 65deg);
-webkit-transform: rotate3d(0, 1, 0, 65deg);
// 这里会展示3D效果
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
// 不展示3D效果
// transform-style: flat;
// -webkit-transform-style: flat;
}
.stage .box .box-out {
width: 90%;
height: 90%;
background-color: #ffff00;
transform: rotate3d(0.5, 1, 0, 85deg);
-webkit-transform: rotate3d(0.5, 1, 0, 85deg);
}
.stage .box .box-out .box-in {
width: 150%;
height: 150%;
background-color: #aaff7f;
transform: rotate3d(0.1, 1, 0.5, 85deg);
-webkit-transform: rotate3d(0.1, 1, 0.5, 85deg);
}
背面是否可见属性(backface-visibility)
backface-visibility属性定义当元素不面向屏幕时是否可见backface-visibility: visible | hidden,visible表示背面是可见的,hidden表示背面不可见- 该属性主要用于不想展示被旋转元素的背面时使用,通常用于一些翻转动效,比如炉石的抽卡,就属于背面可见
- 下面我们可以通过翻拍效果示例来理解一下这个属性的作用
<div class="stage">
<div class="box">
<div class="box-prev"></div>
<div class="box-next"></div>
</div>
</div>
.stage {
width: 100%;
height: 100%;
perspective: 1600px;
-webkit-perspective: 1600px;
}
.box {
width: 400px;
height: 400px;
margin: 100px 100px;
position: relative;
transition: 0.5s all;
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
}
.box-prev,
.box-next {
width: 100%;
height: 100%;
position: absolute;
transition: 0.5s all;
backface-visibility: hidden;
}
.box-prev {
background-color: #ffff00;
z-index: 1;
}
.box-next {
background-color: #aaff7f;
transform: rotateY(180deg);
z-index: 0;
}
.box:hover{
transform: rotateY(180deg);
}
做一些简单的循环动效
学习了上述代码之后,我们可以做一些简单的循环动效了,这里我们用一个简单的翻书效果来练习,当然还有很多奇思妙想期待你自己去实践啦!
<div class="stage">
<div class="box">
<div class="box-prev"></div>
<div class="box-midd"></div>
<div class="box-next">
<span></span>
<span></span>
</div>
</div>
</div>
.stage {
width: 100%;
height: 100%;
}
.box {
width: 400px;
height: 400px;
margin: 100px 100px;
position: relative;
transition: 0.5s all;
transform-style: preserve-3d;
}
.box-prev,
.box-midd,
.box-next {
width: 100%;
height: 100%;
position: absolute;
transition: 3s all;
}
.box-prev {
background-color: #ffff9b;
z-index: 2;
}
.box-midd {
background-color: #aaff7f;
z-index: 1;
}
.box-next {
display: flex;
justify-content: space-between;
z-index: 0;
}
.box-next span {
width: 50%;
height: 100%;
}
.box-next span:nth-child(1) {
background-color: #ffff9b;
}
.box-next span:nth-child(2) {
background-color: #aaff7f;
}
.box:hover .box-prev {
transform: perspective(800px) rotateY(-180deg);
transform-origin: perspective(800px) 50% 50% 0;
}
.box:hover .box-midd {
transform: perspective(800px) rotateY(-180deg);
transform-origin: perspective(800px) 50% 50% 0;
}
参考文档一 ———— 带你玩转css3的3D!
参考文档二 ———— 好吧,CSS3 3D transform变换,不过如此!
参考文档三 ———— CSS perspective 属性
参考文档三 ———— CSS perspective-origin 属性
参考文档五 ———— CSS transform 属性
参考文档六 ———— CSS transform-origin 属性
参考文档七 ———— CSS transform-style 属性
参考文档八 ———— CSS backface-visibility 属性
参考文档九 ———— CSS3中设置3D变形的transform-style属性详解
我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~
转发请注明参考文章地址,非常感谢!!!
详解如何用 CSS3 完成 3D transform变换的更多相关文章
- 好吧,CSS3 3D transform变换,不过如此!
一.写在前面的秋裤 早在去年的去年,我就大肆介绍了2D transform相关内容.看过海贼王的都知道,带D的家伙都不是好惹的,2D我辈尚可以应付,3D的话,呵呵,估计我等早就在千里之外被其霸气震晕了 ...
- 好吧,CSS3 3D transform变换,不过如此!——张鑫旭
一.写在前面的秋裤 早在去年的去年,我就大肆介绍了2D transform相关内容.看过海贼王的都知道,带D的家伙都不是好惹的,2D我辈尚可以应付,3D的话,呵呵,估计我等早就在千里之外被其霸气震晕了 ...
- Safari 3D transform变换z-index层级渲染异常的研究
by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5569 一.Safari是新时代的IE6 在2年前介绍currentColor变量 ...
- 高效开发之SASS篇 灵异留白事件——图片下方无故留白 你会用::before、::after吗 link 与 @import之对比 学习前端前必知的——HTTP协议详解 深入了解——CSS3新增属性 菜鸟进阶——grunt $(#form :input)与$(#form input)的区别
高效开发之SASS篇 作为通往前端大神之路的普通的一只学鸟,最近接触了一样稍微高逼格一点的神器,特与大家分享~ 他是谁? 作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家 ...
- CSS3 3D transform变换
.实际应用-图片的旋转木马效果 您可以狠狠地点击这里:图片的旋转木马效果demo 建议在足够新版本的FireFox浏览器或Safari浏览器下观看,Chrome可能需要居中定位查看,下图为效果缩略图: ...
- iOS 2D绘图详解(Quartz 2D)之Transform(CTM,Translate,Rotate,Scale)
前言:Quartz默认采用设备无关的user space来进行绘图,当context(画板)建立之后,默认的坐标系原点以及方向也就确认了,可以通过CTM(current transformation ...
- 一文详解如何用 TensorFlow 实现基于 LSTM 的文本分类(附源码)
雷锋网按:本文作者陆池,原文载于作者个人博客,雷锋网已获授权. 引言 学习一段时间的tensor flow之后,想找个项目试试手,然后想起了之前在看Theano教程中的一个文本分类的实例,这个星期就用 ...
- 详解如何用AD 生成Gerber文件
以上gerber文件就出完了; 下面步骤是:进行导出" 钻孔文件 ". 以上钻孔文件就出完了; 到此就全部完成输出了. 下面的操作,也可以不用导的 .下面步骤是:进行导出&qu ...
- Safari 3D transform变换z-index层级渲染异常
(猛戳来源:http://www.zhangxinxu.com/wordpress/?p=5569)
随机推荐
- 如何在印刷品中使用遵循SIL Open Font License协议的字体
如何在印刷品中使用遵循SIL Open Font License协议的字体 昨天在知乎看到了一个问题,( 如何在设计中声明字体开源许可证? - 知乎 (zhihu.com),恰好最近在研究一些开源协议 ...
- pycharm安装pika提示CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com>
1. 问题描述: pycharm安装第三方库时提示CondaHTTPError: HTTP 000 CONNECTION FAILED. 2. 错误原因:默认镜像源访问速度过慢,会导致超时从而导致更新 ...
- 自定义Push/Pop和Present/Dismiss转场
项目概述 iOS中最常见的动画无疑是Push和Pop的转场动画了,其次是Present和Dismiss的转场动画. 如果我们想自定义这些转场动画,苹果其实提供了相关的API,在自定义转场之前,我们需要 ...
- 【数据结构与算法Python版学习笔记】图——骑士周游问题 深度优先搜索
骑士周游问题 概念 在一个国际象棋棋盘上, 一个棋子"马"(骑士) , 按照"马走日"的规则, 从一个格子出发, 要走遍所有棋盘格恰好一次.把一个这样的走棋序列 ...
- 技术博客——微信小程序UI的设计与美化
技术博客--微信小程序UI的设计与美化 在alpha阶段的开发过后,我们的小程序也上线了.看到自己努力之后的成果大家都很开心,但对比已有的表情包小程序,我们的界面还有很大的提升空间,许多的界面都是各个 ...
- 如何洗白xi校长?(初稿)
看看咱们太子殿下,谁还敢黑全世界最好的太子殿下 我们不如来考虑一下如何给校长洗白. 第一当然是买断热搜了.买断热搜可以阻止消息进一步传播.当然这种操作学校再8月18日晚就已经做过了.8月18日该条消息 ...
- 关于QGIS的插件开发(C++)
关于C++插件的开发材料较少,根据网上的指导,我采用了早期版本的插件模板生成的方法来创建QGIS的插件,其方法是从以前版本(2.18.25)里面拷贝插件模板的方法进行,具体的执行步骤为 1.拷贝文件 ...
- linux shell 基本语法之快速上手shell编程
从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁.用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操 ...
- 在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。
在Vue前端项目中,我这里主要是基于Vue+Element的开发,大多数情况下,我们利用Element的表格组件就可以满足大多数情况的要求,本篇随笔针对表格的展示和编辑处理,综合性的介绍几款表格组件的 ...
- CSS学习笔记:浮动属性
目录 一.浮动流是什么 二.通过代码实例了解浮动特点 1. 搭建测试框架 2. 添加浮动 3. 浮动元素的排布 4. 给行内元素添加浮动效果 5. 子元素浮动后对父元素的影响 5.1 在父元素中添加o ...