英文原文An Introduction to CSS 3-D Transforms

爱因斯坦说所有概念都必须介绍给儿童们,若他们无法了解,这些理论就毫无价值。

透视

一个元素需要一个透视点才能激活3D空间,有两种方法可以得到透视点:

  1. 使用transform属性,赋上perspective函数作为值。-webkit-transform: perspective(600);
  2. 或使用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笨蛋教程的更多相关文章

  1. 一款非常棒的纯CSS3 3D菜单演示及制作教程

    原文:一款非常棒的纯CSS3 3D菜单演示及制作教程 这段时间比较忙,很久没在这里分享一些漂亮的HTML5和CSS3资源了,今天起的早,看到一款很不错的CSS3 3D菜单,觉得非常上眼,就将它分享给大 ...

  2. CSS3 3D立方体翻转菜单实现教程

    今天我们来看一个非常有创意的CSS3 3D菜单,这个菜单的菜单项是可以旋转的长方体,鼠标滑过是长方体即可旋转,看看下面的效果图,是不是感觉非常酷,我觉得这个菜单很适合用在咱们开发人员的个人网站上. 当 ...

  3. CSS3 3D旋转下拉菜单--兼容性不太好

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  4. 【Web动画】CSS3 3D 行星运转 && 浏览器渲染原理

    承接上一篇:[CSS3进阶]酷炫的3D旋转透视 . 最近入坑 Web 动画,所以把自己的学习过程记录一下分享给大家. CSS3 3D 行星运转 demo 页面请戳:Demo.(建议使用Chrome打开 ...

  5. 纯css3 3D图片立方体旋转动画特效

    纯css3 3D立方体模块,鼠标触碰,模块炸开,大立方体中套小立方体 效果展示 手机扫描二维码体验效果: 效果图如下: 源码下载:http://hovertree.com/h/bjaf/0qmul8g ...

  6. CSS3 3D轮播主要可以分成这样的三类

    中秋节假期这么快就没了,这几天还一直下雨,索性在家看看书.这次看的是Tom Lane的<A Tour of PostgreSQL Internals>.这篇小随笔就算做学习笔记了.园子里面 ...

  7. css3 3D旋转效果

    css3 record2 css3 3D旋转效果 需理解transform css3知识: keyframes transform perspective jsfiddle demo keyframe ...

  8. [应用][js+css3]3D盒子导航[PC端]

    CSS3构建的3D盒子之导航应用 1.在用css3构建的盒子表面,放上iframe,来加载导航页面. 2.鼠标左键按下移动可旋转盒子,寻找想要的网址. 3.左键单机盒子表面,将全屏现实所点盒子表面的网 ...

  9. HTML5之CSS3 3D transform 剖析式学习之一

    最近坐地铁发现“亚洲动物基金”在地铁上做了很多公益广告,比较吸引人的是一个月熊的广告.做的很可爱.回去就搜了一下,发现这个网站是HTML5做的,非常炫. 所以想学习一下,方法就是传统的学习办法,模仿. ...

随机推荐

  1. centos 之7zip

    首先,我得说几句,我第一次进行了实验. 压缩文件夹html rar压缩   成绩5.18M zip压缩  成绩5.06M 7z压缩   成绩870K 第一种,源代码编译安装 官网下载地址:http:/ ...

  2. 经典Loading 动漫赏析

    0. 传统的菊花Loading动画 假设作为程序猿的你还在用菊花作为Loading动画,是时候换个口味了.来看下5种不错的Loading动画. 几种颜色组成的动画,给用户一个美感. 1.android ...

  3. lcc之内存分配

    现在感觉这本书有些地方没有说透,如果自己的理解能力与基础知识够强的话,理解起来还好,如果不行的话,某些地方理解起来会相当的头疼. 现在来说说内存管理.当初看这一章的时候很快就过去了,感觉很多地方很好理 ...

  4. 编译预处理 -- 带参数的宏定义--【sky原创】

    原文:编译预处理 -- 带参数的宏定义--[sky原创] 如有转载请注明出处   编译预处理  --  带参数的宏定义 前面为输出文件,后面为输入文件 gcc -E -o test.i test.c ...

  5. Android KeyStore Stack Buffer Overflow (CVE-2014-3100)

    /* 本文章由 莫灰灰 编写,转载请注明出处. 作者:莫灰灰    邮箱: minzhenfei@163.com */ 1. KeyStore Service 在Android中,/system/bi ...

  6. win7访问xp共享访问不了

    这个问题不是一天两天了,经历几次了,所以记下来. 1. 一些XP对用户权限作了特殊的优化设置.限制了只有guest用户才能用于做局域网共享用户. 2. 大多数时候,需要设置一个密码,才能用于访问. 3 ...

  7. 来选择一款适合你网站的CMS建站程序吧

    1:首页我们要搞清楚什么叫cms? ContentManagementSystem就是cms的全名,意思就是内容管理系统.cms整站系统是以文章系统为核心,增加用户需要的模块,如文章.图片.下载等,提 ...

  8. [翻译]如何编写GIMP插件(二)

    写在前面: 本人翻译并不专业,甚至英语不好,翻译内容仅供参考.由于博主是边学边翻译,所以不能保证翻译的准确性和正确性,如果可以,请查看原版学习,本文仅作学习记录之用. <How to write ...

  9. PhpStorm创建Drupal模块项目开发教程(5)

    Drupal项目开发中,问题跟踪器的设置,可以保证信息的交互.是开发中,不可或缺的部分. 接下来,就PhpStorm IDE中,问题跟踪器集成的配置操作就行图文解说. Settings | Tasks ...

  10. win7兼容oracle

    操作系统:win7,数据库版本:Oracle 10.0. 问题:安装Oracle10.0时,安装程序意外退出,可按照如下操作解决win7与oracle兼容性问题. 1.打开“\Oracle 10G \ ...