Intro to CSS 3D transforms

原文地址:Intro to CSS 3D transforms,本文只是翻译了其中的一部分,省去了做者写文章的缘由浏览器兼容部分(已通过时)
css

Perspective

元素须要设置须要设置perspective来激活3D效果,能够经过两种方式实现html

  • 在transform属性中使用perspective方法html5

    transform: perspective( 600px );
  • 直接使用perspective属性css3

    perspective: 600px;

NOTE:出于代码简介的目的,demo中的CSS样式没有使用浏览器前缀,在实际使用中须要使用-webkit-perspective, -moz-perspective, 等git

<style>
    .container {
        width: 200px;
        height: 200px;
        border: 1px solid #CCC;
        margin: 0 auto 40px;
    }
    .box {
        width: 100%;
        height: 100%;
    }
    #red1 .box {
      background-color: red;
      transform: perspective( 600px ) rotateY( 45deg );
    }
</style>
<section id="red1" class="container">
    <div class="box red"></div>
</section>

 

<style>
    #blue1{
        perspective: 600px;
    }
    #blue1 .box {
      background-color: blue;
      transform: rotateY( 45deg );
    }
</style>

<section id="blue1" class="container">
    <div class="box blue1"></div>
</section>

 

这两种方式都会触发3D效果,可是有一点不一样:第一种方式直接在一个元素上触发3D变形,可是当多个元素的时候变形效果和预期会有所不一样,若是使用一样的方法做用于不一样位置的元素的时候,每一个元素会有本身的轴心,为了解决这个问题,须要在父元素使用perspective属性,这样每一个子元素都共享相同的3D空间github

<style>
    #red2 figure {
      background: red;
      transform: perspective( 400px ) rotateY(45deg);
    }
    .container figure {
        display: block;
        width: 55px;
        height: 55px;
        float: left;
        margin: 5px;
    }

    #red2 figure {
        background: #F00;
        -webkit-transform: perspective( 400px ) rotateY( 45deg );
        -moz-transform: perspective( 400px ) rotateY( 45deg );
        -o-transform: perspective( 400px ) rotateY( 45deg );
        transform: perspective( 400px ) rotateY( 45deg );
    }
</style>
<section id="red2" class="container">
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
</section>

 

<style>
    #blue2 {
      perspective: 400px;
    }

    #blue2 figure {
      background: blue;
      transform: rotateY( 45deg );
    }
</style>
<section id="blue2" class="container">
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
    <figure></figure>
</section>

 

perspective属性的值决定了3D效果的强烈程度,能够认为是观察者到页面的距离。值越大距离越远,视觉上的3D效果就会相应的减弱。perspective: 2000px; 会产生一个好像咱们使用望远镜看远方物体的3D效果,perspective: 100px;会产生一个小昆虫看大象的效果。web

3D效果默认轴心是元素中央,能够经过perspective-origin来修改轴心浏览器

perspective-origin: 25% 75%;

点击这里看一下做者写的一个有意思的立方体旋转页面ide

3D变形方法

做为一个web者,可能很熟悉两个方向:X & Y,表示元素的水平方向和垂直方向,在perspective激活的3D空间中咱们能够在X、Y、Z三个坐标轴上对元素进行变形处理。3D变形使用的变形方法和2D变形同样,若是熟悉2D变形方法很容易掌握3D变形函数

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

translateX()方法使元素延X轴移动,translateZ()使元素延Z轴(在3D空间中方向从前到后)移动。正值使元素离观察者更近,负值使元素变远。

translateZ( -200px )


translateZ( 200px )


rotateX( 45deg )


rotateY( 45deg )


rotateZ( 45deg )

有几个变形方法的缩写,这些方法须要把三个参数写全

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

Pro-tip: fn3d()变形方法能够触发硬件加速HTML5 buzzwords in action

任意3D操做会触发硬件加速,甚至可能变形只用到了2D的,或者没有作任何事情(好比translate3d(0,0,0))。须要注意的是这只是当前的表现,将来可能变化(这也是为何咱们没有写文档或者鼓励这么作),可是这在不少场景下很是有用,能够显著的提升渲染性能

立方体

建立六个面

<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>

为6个面设置基本的位置和尺寸样式

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

#cube {
  width: 100%;
  height: 100%;
  position: absolute;
  transform-style: preserve-3d;
}

#cube figure {
  width: 196px;
  height: 196px;
  display: block;
  position: absolute;
  border: 2px solid black;
}

一、2是先后面,三、4是左右,五、6是上下

#cube .front  { transform: rotateY(   0deg ); }
#cube .back   { transform: rotateX( 180deg ); }
#cube .right  { transform: rotateY(  90deg ); }
#cube .left   { transform: rotateY( -90deg ); }
#cube .top    { transform: rotateX(  90deg ); }
#cube .bottom { transform: rotateX( -90deg ); }

咱们能够移除#cube .front样式声明,只用前面是可见的,上、下、左、右面与视角平行,因此看不到。须要从中心位置移动它们才能够看获得,每一个面都是200px宽,每一个面都须要从立方体中心移动100px;

#cube .front  { transform: rotateY(   0deg ) translateZ( 100px ); }
#cube .back   { transform: rotateX( 180deg ) translateZ( 100px ); }
#cube .right  { transform: rotateY(  90deg ) translateZ( 100px ); }
#cube .left   { transform: rotateY( -90deg ) translateZ( 100px ); }
#cube .top    { transform: rotateX(  90deg ) translateZ( 100px ); }
#cube .bottom { transform: rotateX( -90deg ) translateZ( 100px ); }

须要注意的是translateZ方法在rotate方法以后,变形方法的顺序很重要,吸取一下子屌丝们,每面都先按本身的方向旋转,而后向外移动一个向量。

为了用户看清楚,咱们的3D变形不该该在扭曲不是active的面,可是咱们延Z轴移动的时候,这种状况就难以免。为了保持3D变形的瞬间,Safari先组合元素,而后再应用变形,所以文本会保持变形以前的样式,在3D变形中常常会出现显著的像素变化

font-size: 2.5em


transform: scale(2.5);


transform: perspective(1200) translateZ(700px);

经过以前例子能够发现不管perspective的值多小,或者变形的轴心在哪里,面1永远回到初始位置,好像3D变形对它没影响

为了解决变形和像素保留问题,咱们能够向后推一下3D对象,这样前面就会Z轴后移

#cube { transform: translateZ( -100px ); }

为了显示每一个面,咱们须要一个旋转立方体的样式,变形和当前面的方向相反,咱们在#box 上切换必要的类来应用变形

#cube.show-front  { transform: translateZ( -100px ) rotateY(    0deg ); }
#cube.show-back   { transform: translateZ( -100px ) rotateX( -180deg ); }
#cube.show-right  { transform: translateZ( -100px ) rotateY(  -90deg ); }
#cube.show-left   { transform: translateZ( -100px ) rotateY(   90deg ); }
#cube.show-top    { transform: translateZ( -100px ) rotateX(  -90deg ); }
#cube.show-bottom { transform: translateZ( -100px ) rotateX(   90deg ); }

须要注意变形方法的顺序变了,咱们先向后推元素,而后再旋转,再添加transition属性就完成了

#cube { transition: transform 1s; }

效果demo

旋转木马

和建立立方体相似,咱们建立一个9个面的旋转木马

<section 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>
</section>

如今应用一下基本的布局样式,给每一个#carousel子元素面板20px的间距,这样每一个面板的空间为210px

.container {
  width: 210px;
  height: 140px;
  position: relative;
  perspective: 1000px;
}

#carousel {
  width: 100%;
  height: 100%;
  position: absolute;
  transform-style: preserve-3d;
}

#carousel figure {
  display: block;
  position: absolute;
  width: 186px;
  height: 116px;
  left: 10px;
  top: 10px;
  border: 2px solid black;
}

下一步须要旋转每一个面,9个面板,若是等分的话每一个面板须要旋转40deg相对下一个

#carousel figure:nth-child(1) { transform: rotateY(   0deg ); }
#carousel figure:nth-child(2) { transform: rotateY(  40deg ); }
#carousel figure:nth-child(3) { transform: rotateY(  80deg ); }
#carousel figure:nth-child(4) { transform: rotateY( 120deg ); }
#carousel figure:nth-child(5) { transform: rotateY( 160deg ); }
#carousel figure:nth-child(6) { transform: rotateY( 200deg ); }
#carousel figure:nth-child(7) { transform: rotateY( 240deg ); }
#carousel figure:nth-child(8) { transform: rotateY( 280deg ); }
#carousel figure:nth-child(9) { transform: rotateY( 320deg ); }

如今外移元素,咱们须要计算外移的距离,画一个草图,咱们发现只有两个已知数:每一个面板的宽度是210px,每一个面板相对下一个旋转了40deg。拿出任意一个三角形都是右边的样子

咱们能够经过正切函数算出r

image

这样咱们就知道知道须要移动288px

#carousel figure:nth-child(1) { transform: rotateY(   0deg ) translateZ( 288px ); }
#carousel figure:nth-child(2) { transform: rotateY(  40deg ) translateZ( 288px ); }
#carousel figure:nth-child(3) { transform: rotateY(  80deg ) translateZ( 288px ); }
#carousel figure:nth-child(4) { transform: rotateY( 120deg ) translateZ( 288px ); }
#carousel figure:nth-child(5) { transform: rotateY( 160deg ) translateZ( 288px ); }
#carousel figure:nth-child(6) { transform: rotateY( 200deg ) translateZ( 288px ); }
#carousel figure:nth-child(7) { transform: rotateY( 240deg ) translateZ( 288px ); }
#carousel figure:nth-child(8) { transform: rotateY( 280deg ) translateZ( 288px ); }
#carousel figure:nth-child(9) { transform: rotateY( 320deg ) translateZ( 288px ); }

若是须要改变面板的宽度或者数量,咱们只须要应用一下公式就能够了,在JavaScript中

var tz = Math.round( ( panelSize / 2 ) / 
  Math.tan( ( ( Math.PI * 2 ) / numberOfPanels ) / 2 ) );
// or simplified to
var tz = Math.round( ( panelSize / 2 ) / 
  Math.tan( Math.PI / numberOfPanels ) );

最后咱们须要再旋转木立刻应用些变形

transform: translateZ( -288px ) rotateY( -160deg );

JS Bin

相关文章
相关标签/搜索