Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS3之3d transform #2

Open
simaQ opened this issue Nov 17, 2014 · 0 comments
Open

CSS3之3d transform #2

simaQ opened this issue Nov 17, 2014 · 0 comments

Comments

@simaQ
Copy link
Owner

simaQ commented Nov 17, 2014

原文地址: 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 simaQ added this to the 小飞飞的css译文 milestone Nov 17, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant