CSS3 3D笨蛋教程
英文原文An Introduction to CSS 3-D Transforms
爱因斯坦说所有概念都必须介绍给儿童们,若他们无法了解,这些理论就毫无价值。
透视
一个元素需要一个透视点才能激活3D空间,有两种方法可以得到透视点:
- 使用transform属性,赋上perspective函数作为值。
-webkit-transform: perspective(600);
- 或使用perspective属性。
-webkit-perspective: 600;
左边是使用transform属性的,右边使用perspective属性
这两种方法都能触发3D空间,但却有所不同。首先,使用函数方式可以方便快捷地对单一元素应用3D变形,但是当你要应用在多个元素上时,它们可能不会按照预期的效果排列。如果你使用同样的transform属性应用在多个不同位置的元素上,每个元素都有自己的消失点。为了避免这种滑稽的效果,使用perspective属性应用在它们的父容器元素上,这样每个元素都共享了同一个消失点。
左边是使用transform属性的,右边使用perspective属性
perspective属性的值决定了3D效果的强度。
你拿一本书平放在面前,看着书感受一下透视感,perspective属性值就是眼睛和书之间的距离,距离越远,数值越大,透视感越小;距离越近,数值越小,透视感越强。
默认情况下,3D空间的消失点位于空间的正中央,你可以通过perspective-origin属性改变消失点的位置。
CSS
-webkit-perspective-origin: 25% 75%;
3D变形函数
作为一个Web设计师,你可能非常熟悉二维世界,X和Y,水平和垂直方向。在perspective创建的三维空间中,我们可以在三个维度上任意变换一个元素。
3D变形使用的是和2D变形类似的transform属性。如果你熟悉2D变形,你会发现它和基本的3D变形很像。
CSS
rotateX(angle);
rotateY(angle);
rotateZ(angle);
translateZ(tz);
scaleZ(sz);
我们借鉴translateX()这个函数,它令一个元素沿着水平X轴方向平移,而translateZ()函数则是沿着垂直的Z轴方向平移,它可以让3D空间由前往后运作。假设自己作为观察者,观察着电脑屏幕上的某个元素,translateZ函数的正向值(越来越大的值)令元素更靠近观察者,负向值则远离观察者。
rotate函数可以在特定轴向上旋转元素。它的效果不同于你的直觉,通过下图可以很直观的感受到。
可能很多人直觉中认为rotateX的效果会是rotateZ那个样子。
transform函数的一些简写:
CSS
translate3d(tx,ty,tz);
scale3d(sx,sy,sz);
rotate3d(rx,ry,rz,angle);
专家提醒:这些foo3d()变形函数在safari浏览器中会触发硬件加速效果。
翻转卡片
需要一些基本的标签:
HTML
<section class="container">
<div id="card">
<figure class="front">1</figure>
<figure class="back">2</figure>
</div>
</section>
.container元素持有3D空间,#card作为一张卡片对象。卡片的每一面就是一个独立的元素:.front和.back。将3d空间内的各个元素独立化,可以更容易理解和应用样式。
我们准备添加一些3D样式:首先,对3D容器应用必要的perspective属性,同时添加任意的高宽或位置属性:
CSS
.container {
width: 200px;
height: 260px;
position: relative;
-webkit-perspective: 800;
}
现在#card元素可以在该3D空间中进行变形了。我们给#card元素添加绝对位置属性让它脱离文档的流式布局,再加上width:100%;
和height:100%
,保证该对象的transform-origin可以在.center的正中央生效。
让我们加上CSS3的transition属性,这样用户可以看到整个变形过程。
CSS
#card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
-webkit-transition: -webkit-transform 1s;
}
.container的perspective仅仅应用在直接后代元素上,在本例中是应用在#card上。为了让所有后代元素都继承父元素的透视效果并在同样的3D空间中生效,父元素需要通过transform-style:preserve-3d
来传递它的透视属性。如果没有transform-style,卡片的两个面都会失去立体效果,并且背面的旋转效果也会失效。
要将卡片的两面定位到3D空间中,我们需要重置这些面元素的2D位置属性position:absolute。
当卡片的正面朝向观察者时,为了隐藏相反的另一面,也就是背面,我们可以使用backface-visibility:hidden。
CSS
#card figure {
display: block;
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
}
要翻转.back面,我们添加基本的3D变形rotateY(180deg)
。
CSS
#card .front {
background: red;
}
#card .back {
background: blue;
-webkit-transform: rotateY(180deg);
}
将两个面都设置好之后,#card需要一个相应的样式来翻转卡片。
CSS
#card.flipped {
-webkit-transform: rotateY(180deg);
}
现在我们具备了一个可用的3D对象。为了翻转这张卡片,我们可以切换flipped类。当.flipped添加到#card上时,#card会旋转180度,将.back面露出来。
立方体
3D卡片对象是3D变形的入门好教材,一旦熟练掌握,你可能希望创建一些真正3D对象,例如棱柱。下面我们从立方体开始。 立方体的HTML标签和卡片类似,但是这次,我们需要六个子元素来创建立方体的六个面:
HTML
<section class="container">
<div id="cube">
<figure class="front">1</figure>
<figure class="back">2</figure>
<figure class="right">3</figure>
<figure class="left">4</figure>
<figure class="top">5</figure>
<figure class="bottom">6</figure>
</div>
</section>
先给六个面设置基本的定位和尺寸样式,一个叠一个放置在容器里。
CSS
.container {
width: 200px;
height: 200px;
position: relative;
-webkit-perspective: 1000;
}
#cube {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
}
#cube figure {
width: 196px;
height: 196px;
display: block;
position: absolute;
border: 2px solid black;
}
对于卡片,我们只需要翻转它的背面。对于立方体,需要翻转六个面中的五个。我们称第一面和第二面为前面和后面,第三第四面为侧面,第五第六面为顶面和底面。
CSS
#cube .front { -webkit-transform: rotateY(0deg); }
#cube .back { -webkit-transform: rotateX(180deg); }
#cube .right { -webkit-transform: rotateY(90deg); }
#cube .left { -webkit-transform: rotateY(-90deg); }
#cube .top { -webkit-transform: rotateX(90deg); }
#cube .bottom { -webkit-transform: rotateX(-90deg); }
现在每个面都旋转好了,并且只能看到正面。有四个面是垂直于观察者的,所以他们完全不可见。然后要使translate函数将他们从中心位置推到正确的边上。立方体的每个边长是200像素,从中心到边缘,每个边需要平移100像素。
CSS
#cube .front { -webkit-transform: rotateY(0deg) translateZ(100px); }
#cube .back { -webkit-transform: rotateX(180deg) translateZ(100px); }
#cube .right { -webkit-transform: rotateY(90deg) translateZ(100px); }
#cube .left { -webkit-transform: rotateY(-90deg) translateZ(100px); }
#cube .top { -webkit-transform: rotateX(90deg) translateZ(100px); }
#cube .bottom { -webkit-transform: rotateX(-90deg) translateZ(100px); }
注意这里的translateZ函数紧接在rotate之后。顺序对于变形函数来说是很重要的,请花一些时间消化这句话。每一个面要先旋转到正确的朝向,然后沿着各自的朝向向外平移。
现在我们的立方体看起来能用了,但还没完成。
回到Z轴源点
对于使用者,我们的3D变形不应该失真。但是当我们将元素从Z轴源点移开之后,不论是靠近观察者还是远离观察者,它都会失真。
为了让3D变形看上去严谨,Safari先将元素复合,然后对其应用变形效果。也就是说,文本的抗锯齿效果会一直保持在变形之前的状态。
为了解决失真问题,并还原像素,我们可以将整个3D对象向后推,这样它的正面将回到Z轴源点。
CSS
#cube { -webkit-transform: translateZ(-100px); }
转动立方体
我们需要一个能暴露任意面的样式。事实上我们只需要对整个立方体对象动手脚,在这里,立方体对象就是#cube。我们切换类名来应用不同的样式,一种样式就是一种变形,暴露不同的面。
CSS
#cube.show-front { -webkit-transform: translateZ(-100px) rotateY(0deg); }
#cube.show-back { -webkit-transform: translateZ(-100px) rotateX(-180deg); }
#cube.show-right { -webkit-transform: translateZ(-100px) rotateY(-90deg); }
#cube.show-left { -webkit-transform: translateZ(-100px) rotateY(90deg); }
#cube.show-top { -webkit-transform: translateZ(-100px) rotateX(-90deg); }
#cube.show-bottom { -webkit-transform: translateZ(-100px) rotateX(90deg); }
注意这里变形函数的次序和每个面的函数次序相反,首先要把立方体推回Z轴源点,然后旋转立方体。 完成之后,我们添加一个transition属性来展现旋转时的动画效果。
CSS
#cube { -webkit-transition: -webkit-transform 1s; }
矩形棱柱
立方体很容易制作,它是规则的,我们只需要关心一个度量值。但对于一个不规则的矩形棱柱呢?让我们尝试做一个300像素长,200像素宽,100像素高的棱柱。
HTML标签和#cube的一样,但我们要把cube换成box,容器的样式保留大部分:
CSS
.container {
width: 300px;
height: 200px;
position: relative;
-webkit-perspective: 1000;
}
#box {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
}
现在定位各个面。每个面需要设置他们自己的尺寸,较小的面(左、右、顶、底)要定位到容器的正中央,这样他们可以方便地旋转然后置换到外侧。较薄的左面和右面设置位置为left:100px;((300-100)÷2)。较宽大的顶面和底面设置位置为top:500px((200-100)÷2)。
CSS
#box figure {
display: block;
position: absolute;
border: 2px solid black;
}
#box .front,
#box .back {
width: 296px;
height: 196px;
}
#box .right,
#box .left {
width: 96px;
height: 196px;
left: 100px;
}
#box .top,
#box .bottom {
width: 296px;
height: 96px;
top: 50px;
}
旋转值可以和立方体案例中一致,但对于矩形棱柱,平移值需要一些变化。
CSS
#box .front { -webkit-transform: rotateY(0deg) translateZ(50px); }
#box .back { -webkit-transform: rotateX(180deg) translateZ(50px); }
#box .right { -webkit-transform: rotateY(90deg) translateZ(150px); }
#box .left { -webkit-transform: rotateY(-90deg) translateZ(150px); }
#box .top { -webkit-transform: rotateX(90deg) translateZ(100px); }
#box .bottom { -webkit-transform: rotateX(-90deg) translateZ(100px); }
就像立方体一样,#box需要六个样式来暴露各个面。
CSS
#box.show-front { -webkit-transform: translateZ(-50px) rotateY(0deg); }
#box.show-back { -webkit-transform: translateZ(-50px) rotateX(-180deg); }
#box.show-right { -webkit-transform: translateZ(-150px) rotateY(-90deg); }
#box.show-left { -webkit-transform: translateZ(-150px) rotateY(90deg); }
#box.show-top { -webkit-transform: translateZ(-100px) rotateX(-90deg); }
#box.show-bottom { -webkit-transform: translateZ(-100px) rotateX(90deg); }
旋转木马
本例的HTML标签和矩形棱柱、立方体、卡片一样。让我们构建一个9个面的木马。
HTML
<div class="container">
<div id="carousel">
<figure>1</figure>
<figure>2</figure>
<figure>3</figure>
<figure>4</figure>
<figure>5</figure>
<figure>6</figure>
<figure>7</figure>
<figure>8</figure>
<figure>9</figure>
</div>
</div>
现在,应用一些基本的布局样式。让我们用left属性和right属性给每个面之间添加20像素的间距。每个面的有效宽度为210像素(其中实际为186像素,两边各2像素边框,边框外各10像素空隙,一共210像素)。
CSS
.container {
width: 210px;
height: 140px;
position: relative;
-webkit-perspective: 1000;
}
#carousel {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
}
#carousel figure {
display: block;
position: absolute;
width: 186px;
height: 116px;
left: 10px;
top: 10px;
border: 2px solid black;
}
下一步,旋转每个面。该旋转木马由9个面构成,要让9个面围成一圈,每个面要旋转40度(360÷9)。
CSS
#carousel figure:nth-child(1) { -webkit-transform: rotateY(0deg); }
#carousel figure:nth-child(2) { -webkit-transform: rotateY(40deg); }
#carousel figure:nth-child(3) { -webkit-transform: rotateY(80deg); }
#carousel figure:nth-child(4) { -webkit-transform: rotateY(120deg); }
#carousel figure:nth-child(5) { -webkit-transform: rotateY(160deg); }
#carousel figure:nth-child(6) { -webkit-transform: rotateY(200deg); }
#carousel figure:nth-child(7) { -webkit-transform: rotateY(240deg); }
#carousel figure:nth-child(8) { -webkit-transform: rotateY(280deg); }
#carousel figure:nth-child(9) { -webkit-transform: rotateY(320deg); }
现在每个面都位于旋转木马对象的正中央,像之前制作立方体和矩形棱柱时一样,每个面要向外推到正确的位置上。这里我们需要机选translate函数的值,看图:
这张图是俯瞰该旋转木马对象,210像素是每个面的宽,r就是translate的值,简单的三角函数运算。
我们要将每个面向外推288像素。
CSS
#carousel figure:nth-child(1) { -webkit-transform: rotateY(0deg) translateZ(288px); }
#carousel figure:nth-child(2) { -webkit-transform: rotateY(40deg) translateZ(288px); }
#carousel figure:nth-child(3) { -webkit-transform: rotateY(80deg) translateZ(288px); }
#carousel figure:nth-child(4) { -webkit-transform: rotateY(120deg) translateZ(288px); }
#carousel figure:nth-child(5) { -webkit-transform: rotateY(160deg) translateZ(288px); }
#carousel figure:nth-child(6) { -webkit-transform: rotateY(200deg) translateZ(288px); }
#carousel figure:nth-child(7) { -webkit-transform: rotateY(240deg) translateZ(288px); }
#carousel figure:nth-child(8) { -webkit-transform: rotateY(280deg) translateZ(288px); }
#carousel figure:nth-child(9) { -webkit-transform: rotateY(320deg) translateZ(288px); }
如果我们决定改变每个面的宽度或面的数量,我们只需要写一个JS函数,改变两个变量来获取正确的translateZ值。
JavaScript
var tz = Math.round( ( panelSize / 2 ) / Math.tan( ( ( Math.PI * 2 ) / numberOfPanels ) / 2 ) );
// 或简单点
var tz = Math.round( ( panelSize / 2 ) / Math.tan( Math.PI / numberOfPanels ) );
总结经验
即便是狭义相对论,去找一集BBC看一遍,相信你也能知道是什么东西,虽然不一定能明白背后运作的物理学定理。本文讲述的是CSS3D各种变形函数基本用法,这些函数实际上是对matrix3d()函数的封装,而matrix3d()函数则牵扯到线性代数、立体几何、三角学等的各种知识。未来的前端开发会变成什么样??
CSS3 3D笨蛋教程的更多相关文章
- 一款非常棒的纯CSS3 3D菜单演示及制作教程
原文:一款非常棒的纯CSS3 3D菜单演示及制作教程 这段时间比较忙,很久没在这里分享一些漂亮的HTML5和CSS3资源了,今天起的早,看到一款很不错的CSS3 3D菜单,觉得非常上眼,就将它分享给大 ...
- CSS3 3D立方体翻转菜单实现教程
今天我们来看一个非常有创意的CSS3 3D菜单,这个菜单的菜单项是可以旋转的长方体,鼠标滑过是长方体即可旋转,看看下面的效果图,是不是感觉非常酷,我觉得这个菜单很适合用在咱们开发人员的个人网站上. 当 ...
- CSS3 3D旋转下拉菜单--兼容性不太好
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- 【Web动画】CSS3 3D 行星运转 && 浏览器渲染原理
承接上一篇:[CSS3进阶]酷炫的3D旋转透视 . 最近入坑 Web 动画,所以把自己的学习过程记录一下分享给大家. CSS3 3D 行星运转 demo 页面请戳:Demo.(建议使用Chrome打开 ...
- 纯css3 3D图片立方体旋转动画特效
纯css3 3D立方体模块,鼠标触碰,模块炸开,大立方体中套小立方体 效果展示 手机扫描二维码体验效果: 效果图如下: 源码下载:http://hovertree.com/h/bjaf/0qmul8g ...
- CSS3 3D轮播主要可以分成这样的三类
中秋节假期这么快就没了,这几天还一直下雨,索性在家看看书.这次看的是Tom Lane的<A Tour of PostgreSQL Internals>.这篇小随笔就算做学习笔记了.园子里面 ...
- css3 3D旋转效果
css3 record2 css3 3D旋转效果 需理解transform css3知识: keyframes transform perspective jsfiddle demo keyframe ...
- [应用][js+css3]3D盒子导航[PC端]
CSS3构建的3D盒子之导航应用 1.在用css3构建的盒子表面,放上iframe,来加载导航页面. 2.鼠标左键按下移动可旋转盒子,寻找想要的网址. 3.左键单机盒子表面,将全屏现实所点盒子表面的网 ...
- HTML5之CSS3 3D transform 剖析式学习之一
最近坐地铁发现“亚洲动物基金”在地铁上做了很多公益广告,比较吸引人的是一个月熊的广告.做的很可爱.回去就搜了一下,发现这个网站是HTML5做的,非常炫. 所以想学习一下,方法就是传统的学习办法,模仿. ...
随机推荐
- centos 之7zip
首先,我得说几句,我第一次进行了实验. 压缩文件夹html rar压缩 成绩5.18M zip压缩 成绩5.06M 7z压缩 成绩870K 第一种,源代码编译安装 官网下载地址:http:/ ...
- 经典Loading 动漫赏析
0. 传统的菊花Loading动画 假设作为程序猿的你还在用菊花作为Loading动画,是时候换个口味了.来看下5种不错的Loading动画. 几种颜色组成的动画,给用户一个美感. 1.android ...
- lcc之内存分配
现在感觉这本书有些地方没有说透,如果自己的理解能力与基础知识够强的话,理解起来还好,如果不行的话,某些地方理解起来会相当的头疼. 现在来说说内存管理.当初看这一章的时候很快就过去了,感觉很多地方很好理 ...
- 编译预处理 -- 带参数的宏定义--【sky原创】
原文:编译预处理 -- 带参数的宏定义--[sky原创] 如有转载请注明出处 编译预处理 -- 带参数的宏定义 前面为输出文件,后面为输入文件 gcc -E -o test.i test.c ...
- Android KeyStore Stack Buffer Overflow (CVE-2014-3100)
/* 本文章由 莫灰灰 编写,转载请注明出处. 作者:莫灰灰 邮箱: minzhenfei@163.com */ 1. KeyStore Service 在Android中,/system/bi ...
- win7访问xp共享访问不了
这个问题不是一天两天了,经历几次了,所以记下来. 1. 一些XP对用户权限作了特殊的优化设置.限制了只有guest用户才能用于做局域网共享用户. 2. 大多数时候,需要设置一个密码,才能用于访问. 3 ...
- 来选择一款适合你网站的CMS建站程序吧
1:首页我们要搞清楚什么叫cms? ContentManagementSystem就是cms的全名,意思就是内容管理系统.cms整站系统是以文章系统为核心,增加用户需要的模块,如文章.图片.下载等,提 ...
- [翻译]如何编写GIMP插件(二)
写在前面: 本人翻译并不专业,甚至英语不好,翻译内容仅供参考.由于博主是边学边翻译,所以不能保证翻译的准确性和正确性,如果可以,请查看原版学习,本文仅作学习记录之用. <How to write ...
- PhpStorm创建Drupal模块项目开发教程(5)
Drupal项目开发中,问题跟踪器的设置,可以保证信息的交互.是开发中,不可或缺的部分. 接下来,就PhpStorm IDE中,问题跟踪器集成的配置操作就行图文解说. Settings | Tasks ...
- win7兼容oracle
操作系统:win7,数据库版本:Oracle 10.0. 问题:安装Oracle10.0时,安装程序意外退出,可按照如下操作解决win7与oracle兼容性问题. 1.打开“\Oracle 10G \ ...