cssfun icon indicating copy to clipboard operation
cssfun copied to clipboard

CSS3之3d transform

Open simaQ opened this issue 9 years ago • 0 comments

原文地址: Intro to css 3D transforms

前言: 作者的这个introduction已经写了有好几年了,我今年(而且今年都快过去了)才看到...果真是渣渣...那句话,人丑朋友又少真的是要多读书。不过我觉得我还是得厚着大脸皮敲下去...

三维世界的坐标系

文章开始之前先来张坐标系图好让大家有个3D概念 1

透视,perspective属性

为了激活3D属性,需要对元素声明perspective属性。有两种声明的方式:

  1. 作为属性transform的值和transform一起声明,就同如下代码一样

    transform: perspective( 600px );
    
  2. 直接使用 perspective属性 声明

    perspective: 600px;
    

例子1: 点击访问demo

#red .box {
  background-color: red;
  transform: perspective( 600px ) rotateY( 45deg );  /*作为transform的值*/
}
#blue {
  perspective: 600px; /* 直接声明perspective属性 */
}
#blue .box {
  background-color: blue;
  transform: rotateY( 45deg );
}

perspective01

这两种方式都能产生3D效果,看上去是产生了一样的效果,但是其实两者还是不同的。transform值的形式适用于单个元素的3D转换效果,就像上个例子一样。但是如果应用于多个元素的话,发生变换的元素并不会表现出一致的效果。因为如果对每个不同位置的元素声明一样的transform属性值,那么他们就会拥有个各自的3D空间的基点了。为了解决这个问题,需要对父元素声明perspective属性,使每个子元素共享一个3D空间了。

例子2: 点击访问demo perspective-children01

#red figure {
  background: red;
  transform: perspective( 400px ) rotateY(45deg);
}
#blue {
  perspective: 400px;
}

#blue figure {
  background: blue;
  transform: rotateY( 45deg );
}

PS: 看不出效果的话,可以改变下perspective的值,这样看到的差别会明显一点

perspective值的大小决定了3D效果的强弱程度。就像人看物体一样,perspective值越大,代表物体离眼睛的距离越远,这样看到的物体就越小。perspective:2000px,产生的效果就像我们用望远镜看一个很远很远的物体,perspective: 100px; 则会让物体看起来很大,就像一只小虫看巨大的物体一样。

元素的3D空间的默认基点坐标位于元素中央。但是可以通过perspective-origin属性来修改: perspective-origin: 25% 75%;

例子3 : 点击访问demo

浏览器支持情况

目前的浏览器支持情况如下: 详情请点击查看 2

3D transform functions

bpj d79g j fpb m enl8c 废话我就不翻译了。。。

3D转换和2D转换方法基本相同,下面就是3D转换方法:

  • rotateX( angle )
  • rotateY( angle )
  • rotateZ( angle )
  • translateZ( tz )
  • scaleZ( sz )

但是不同的是, translateX()方法是使一个元素沿着水平X轴坐标旋转,translateZ()则是沿着Z坐标轴,可以使物体在3D空间从前往后移动。值为正数且越大则元素离屏幕越近,负数则代表离屏幕远。

rotate方法使物体在相应的坐标系进行旋转。不过注意哦,rotateX可不是从二维空间中的从左到右的旋转,而是围绕真文章最开头给大家温习的那张3D图中的X轴旋转,具体看下面的例子。

3D transform也提供了一些简写方法,使用这些方法需要同时声明三个维度的参数:

  • translate3d( tx, ty, tz )
  • scale3d( sx, sy, sz )
  • rotate3d( rx, ry, rz, angle )

提示: 这些3D方法都能够触发Safari的硬件加速,Dean Jackson, CSS 3D transform 技术规范的作者以及主要的Webkit成员这么写道:

“实际上,任何transform的3D操作都会触发硬件加速,即使实际只做了2D转换或者什么也没有做(就像translate3d(0,0,0))。但是这只是目前如此并不代表将来就不会发生变化,这也就是为什么我们没有形成文档或者鼓励这样做的原因。但是这在有些场景下确实很有帮助,可以显著提高渲染的性能。”

这里作者为了简单起见,例子上都只是用了一些基本的转换方法,但是如果你需要在IOS或者Safari的生产环境下使用CSS的话,最好使用foo3d()(指的3D transform的简写方法)来获取最好的渲染性能。

活学活用

1. 卡片翻转

现在大家应该都知道了如何制作3D效果。那就先实现个简单卡片翻转的例子吧。 先看看效果: 请点击

<!-- html结构 -->
<section class="container">
  <div id="card">
    <figure class="front">1</figure>
    <figure class="back">2</figure>
  </div>
</section>

.container 作为舞台元素,声明perspective:800px;属性

.container { 
  width: 200px;
  height: 260px;
  position: relative;
  perspective: 800px;
}

现在#card就可以在container的3D空间内进行各种变换了,声明width: 100%; and height: 100%;是为了保证transform-origin为container的中央位置

#card {
  width: 100%;
  height: 100%;
  position: absolute;
  transform-style: preserve-3d;
  transition: transform 1s;
}

transform-style属性有两个参数,flat|preserve-3d. 前者flat为默认值,表示平面的;后者preserve-3d表示3D透视。一般而言,该声明应用在3D变换的兄弟元素们的父元素上,也就是舞台元素。

backface-visibility: hidden; 当前面元素遮挡住后面的元素时,声明这个属性就可以产生遮挡的效果。

#card figure {
  display: block;
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

首先视觉上我们只能看到.front的卡片,所以需要将.back的卡片沿着Y轴旋转180度至后方,当点击flip按钮的时候,直接让#card再沿着Y轴旋转180度,这个时候front卡片就到视线后方而back卡就被我们看到了。

#card .front {
  background: red;
}
#card .back {
  background: blue;
  transform: rotateY( 180deg );
}
#card.flipped {
  transform: rotateY( 180deg );
}

如果我们想要改变旋转轴的位置呢? 这就是transform-origin的作用了,稍作修改就可以达到以下的效果。 我要更炫点: 请点击

#card { transform-origin: right center; }
/* translateX( -100% )  使元素沿着X轴发生平移 */
#card.flipped {
  transform: translateX( -100% ) rotateY( -180deg );
}

2. 立方体

DEMO: cube1 cube2

这个例子主要向大家介绍下translateZ()方法,它可以帮你理解透视位置。demo

对于没有rotateX以及rotateY的元素,translateZ的功能就是让元素在自己的眼前或近或远。比方说,我们设置元素perspective为201像素,如下: perspective: 201px; 则其子元素,设置的translateZ值越小,则子元素大小越小(因为元素远去,我们眼睛看到的就会变小);translateZ值越大,该元素也会越来越大,当translateZ值非常接近201像素,但是不超过201像素的时候(如200像素),该元素的大小就会撑满整个屏幕(如果父辈元素没有类似overflow:hidden的限制的话)。因为这个时候,子元素正好移到了你的眼睛前面,所谓“一叶蔽目,不见泰山”,就是这么回事。当translateZ值再变大,超过201像素的时候,该元素看不见了——这很好理解:我们是看不见眼睛后面的东西的! 引用自 张鑫旭老师的http://www.zhangxinxu.com/wordpress/2012/09/css3-3d-transform-perspective-animate-transition/

**但是这里需要注意的是translateZ 和 rotate 方法的顺序,顺序的不同会产生不一样的效果。**可以通过以下例子好好感受下~ translateZ

3. 旋转木马

旋转木马

这里主要向大家介绍旋转木马效果计算各个面板translateZ值的方法:

  • 我们现在只知道两个值:
    1. rotateY 的旋转角度(等分,通过 360/元素个数 取得)
    2. 面板的宽

那问题来了,怎么计算translateZ的值呢? 其实很简单,当然不是凭直觉随便选出来的那种简单,因为它还是有公式的,那就用下面这张图来说明吧: diagram 然后我们就可以计算出 r 的值了~ calc

simaQ avatar Nov 17 '14 16:11 simaQ