Using matrix3D to create a cube, as an alternative to multiple transforms?

时间:2015-06-30 13:52:36

标签: css css3 3d css-animations css-transforms

I've been exploring the use of perspective in CSS to create a cube, with the hope that eventually I can animate it.

Currently, each individual square on every face is absolutely positioned CSS 3D transforms, but what I wondered was if it's possible to reduce the amount of code I've written by using transform: matrix3d()?

I can't find an explanation of transform: matrix3d() that makes sense to me, so I'm not sure how to use it, or whether it is in fact what I'm looking for.

Here's a CodePen of what I have so far - unfortunately its static at the moment so it doesn't rotate, but there are 6 sides.

1 个答案:

答案 0 :(得分:1)

简短回答:不,使用matrix3d代码的数量不会减少很多。

答案很长:您可以将多个transform属性(例如translatescalerotation)合并到一个矩阵中。但由于matrix3d()需要16个参数,因此我不会太短。

获取matrix3d参数的简便方法是在浏览器的检查器中选择元素并查看计算值。 困难的方法是自己计算价值。

要计算值,首先要了解每个值的含义。例如,您可以在MDN查找它们。 您会注意到在使用translate3drotationY时(例如您的Codepen中的cubie L8),您需要在矩阵上调整以下值:

cos(rot)    0   sin(rot)   tx
0           1   0          ty
-sin(rot)   0   cos(rot)   tz
0           0   0          1 

txtytztranslateZtranslateYtranslateX

rot是弧度的rotationY

-90度/ 180 * PI为-1.57079633弧度。

cos(1.57)= 0.00079632671

罪(1.57)= ~1

导致

 0.00079632671   0   1                  0
 0               1   0                100
-1               0   0.00079632671   -100
 0               0   0                  1

给我们matrix3d(0.00079632671, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0.00079632671, 0, 0, 100, -100, 1)

你的代码在matrix3d中有L侧(我还添加了一个旋转动画):

	#wrapper {
	  width: 100%;
	  height: 100%;
	  position: relative;
	}
	
	#cube-container {
	  /*width: 100%;*/
	  
	  position: absolute;
	  top: 30%;
	  left: 30%;
	}
	
	#cube-viewport {
	  perspective: 600px;
	  perspective-origin: 150px 150px;
	  max-width: 600px;
	}
	
	#cube {
	  position: relative;
	  height: 300px;
	  width: 300px;
	  transform-style: preserve-3d;
	  transform-origin: 50% 50% -150px;
	  animation: rotate 10s infinite linear;
	  /* opacity: 1;
		 border: 1px black solid;*/
	}
	
	.row {
	  transform-style: preserve-3d;
	  transform-origin: 50% 50% -150px;
	  height: auto;
	}
	
	#cube .cubie {
	  position: absolute;
	  margin: 1px;
	  border: 1px solid black;
	  width: 98px;
	  height: 98px;
	  background-size: 100px;
	  opacity: 1;
	  z-index: -1;
	  text-align: center;
	  font-size: 30px;
	  transform-origin: 0 0;
	}
	
	#cube .cubie.front {
	  background-color: red;
	}
	
	#cube .cubie.back {
	  background-color: blue;
	}
	
	#cube .cubie.right {
	  background-color: green;
	}
	
	#cube .cubie.left {
	  background-color: orange;
	}
	
	#cube .cubie.down {
	  background-color: yellow;
	}
	
	#cube .cubie.top {
	  background-color: white;
	}
	
	.ftl {
	  transform: rotateX(0) translate3d(0, 0, 0);
	}
	
	.fcl {
	  transform: rotateX(0) translate3d(0, 100px, 0);
	}
	
	.fbl {
	  transform: rotateX(0) translate3d(0, 200px, 0);
	}
	
	.ftc {
	  transform: rotateX(0) translate3d(100px, 0, 0);
	}
	
	.fcc {
	  transform: rotateX(0) translate3d(100px, 100px, 0);
	}
	
	.fbc {
	  transform: rotateX(0) translate3d(100px, 200px, 0);
	}
	
	.ftr {
	  transform: rotateX(0) translate3d(200px, 0, 0);
	}
	
	.fcr {
	  transform: rotateX(0) translate3d(200px, 100px, 0);
	}
	
	.fbr {
	  transform: rotateX(0) translate3d(200px, 200px, 0);
	}
	
	.btl {
	  transform: rotateY(180deg) translate3d(-300px, 0, 300px);
	}
	
	.bcl {
	  transform: rotateY(180deg) translate3d(-300px, 100px, 300px);
	}
	
	.bbl {
	  transform: rotateY(180deg) translate3d(-300px, 200px, 300px);
	}
	
	.btc {
	  transform: rotateY(180deg) translate3d(-200px, 0, 300px);
	}
	
	.bcc {
	  transform: rotateY(180deg) translate3d(-200px, 100px, 300px);
	}
	
	.bbc {
	  transform: rotateY(180deg) translate3d(-200px, 200px, 300px);
	}
	
	.btr {
	  transform: rotateY(180deg) translate3d(-100px, 0, 300px);
	}
	
	.bcr {
	  transform: rotateY(180deg) translate3d(-100px, 100px, 300px);
	}
	
	.bbr {
	  transform: rotateY(180deg) translate3d(-100px, 200px, 300px);
	}
	
	.rtl {
	  transform: rotateY(90deg) translate3d(0, 0, 300px);
	}
	
	.rcl {
	  transform: rotateY(90deg) translate3d(0, 100px, 300px);
	}
	
	.rbl {
	  transform: rotateY(90deg) translate3d(0, 200px, 300px);
	}
	
	.rtc {
	  transform: rotateY(90deg) translate3d(100px, 0, 300px);
	}
	
	.rcc {
	  transform: rotateY(90deg) translate3d(100px, 100px, 300px);
	}
	
	.rbc {
	  transform: rotateY(90deg) translate3d(100px, 200px, 300px);
	}
	
	.rtr {
	  transform: rotateY(90deg) translate3d(200px, 0, 300px);
	}
	
	.rcr {
	  transform: rotateY(90deg) translate3d(200px, 100px, 300px);
	}
	
	.rbr {
	  transform: rotateY(90deg) translate3d(200px, 200px, 300px);
	}
	
	.ltl {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 0, -300, 1);
	}
	
	.lcl {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 100, -300, 1);
	}
	
	.lbl {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 200, -300, 1);
	}
	
	.ltc {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 0, -200, 1);
	}
	
	.lcc {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 100, -200, 1);
	}
	
	.lbc {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 200, -200, 1);
	}
	
	.ltr {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 0, -100, 1);
	}
	
	.lcr {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 100, -100, 1);
	}
	
	.lbr {
	  transform: matrix3d(0.00079632671, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0.00079632671, 0, 0, 200, -100, 1);
	}
	
	.utl {
	  transform: rotateX(90deg) translate3d(0, -300px, 0);
	}
	
	.ucl {
	  transform: rotateX(90deg) translate3d(0, -200px, 0);
	}
	
	.ubl {
	  transform: rotateX(90deg) translate3d(0, -100px, 0);
	}
	
	.utc {
	  transform: rotateX(90deg) translate3d(100px, -300px, 0);
	}
	
	.ucc {
	  transform: rotateX(90deg) translate3d(100px, -200px, 0);
	}
	
	.ubc {
	  transform: rotateX(90deg) translate3d(100px, -100px, 0);
	}
	
	.utr {
	  transform: rotateX(90deg) translate3d(200px, -300px, 0);
	}
	
	.ucr {
	  transform: rotateX(90deg) translate3d(200px, -200px, 0);
	}
	
	.ubr {
	  transform: rotateX(90deg) translate3d(200px, -100px, 0);
	}
	
	.dtl {
	  transform: rotateX(-90deg) translate3d(0, 0, 300px);
	}
	
	.dcl {
	  transform: rotateX(-90deg) translate3d(0, 100px, 300px);
	}
	
	.dbl {
	  transform: rotateX(-90deg) translate3d(0, 200px, 300px);
	}
	
	.dtc {
	  transform: rotateX(-90deg) translate3d(100px, 0, 300px);
	}
	
	.dcc {
	  transform: rotateX(-90deg) translate3d(100px, 100px, 300px);
	}
	
	.dbc {
	  transform: rotateX(-90deg) translate3d(100px, 200px, 300px);
	}
	
	.dtr {
	  transform: rotateX(-90deg) translate3d(200px, 0, 300px);
	}
	
	.dcr {
	  transform: rotateX(-90deg) translate3d(200px, 100px, 300px);
	}
	
	.dbr {
	  transform: rotateX(-90deg) translate3d(200px, 200px, 300px);
	}
	
	@keyframes rotate {
	  0% {
	    transform: rotateY(0deg) rotateX(0deg);
	  }
	  100% {
	    transform: rotateY(360deg) rotateX(360deg);
	  }
	}
<div id="wrapper">
  <div id="cube-container">
    <div id="cube-viewport">
      <div id="cube">
        <div class="ftl cubie front">F1</div>
        <div class="ftc cubie front">F4</div>
        <div class="ftr cubie front">F7</div>
        <div class="btl cubie back">B1</div>
        <div class="btc cubie back">B4</div>
        <div class="btr cubie back">B7</div>
        <div class="rtl cubie right">R1</div>
        <div class="rtc cubie right">R4</div>
        <div class="rtr cubie right">R7</div>
        <div class="ltl cubie left">L1</div>
        <div class="ltc cubie left">L4</div>
        <div class="ltr cubie left">L7</div>

        <!-- UP FACE -->
        <!-- LEFT COLUMN (L)  -->
        <div class="utl cubie top">U1</div>
        <div class="ucl cubie top">U2</div>
        <div class="ubl cubie top">U3</div>
        <!-- CENTER COLUMN (C)  -->
        <div class="utc cubie top">U4</div>
        <div class="ucc cubie top">U5</div>
        <div class="ubc cubie top">U6</div>
        <!-- RIGHT COLUMN (R)  -->
        <div class="utr cubie top">U7</div>
        <div class="ucr cubie top">U8</div>
        <div class="ubr cubie top">U9</div>
        <!-- END UP FACE -->

        <div class="fcl cubie front">F2</div>
        <div class="fcc cubie front">F5</div>
        <div class="fcr cubie front">F8</div>
        <div class="bcl cubie back">B2</div>
        <div class="bcc cubie back">B5</div>
        <div class="bcr cubie back">B8</div>
        <div class="rcl cubie right">R2</div>
        <div class="rcc cubie right">R5</div>
        <div class="rcr cubie right">R8</div>
        <div class="lcl cubie left">L2</div>
        <div class="lcc cubie left">L5</div>
        <div class="lcr cubie left">L8</div>

        <div class="fbl cubie front">F3</div>
        <div class="fbc cubie front">F6</div>
        <div class="fbr cubie front">F9</div>
        <div class="bbl cubie back">B3</div>
        <div class="bbc cubie back">B6</div>
        <div class="bbr cubie back">B9</div>
        <div class="rbl cubie right">R3</div>
        <div class="rbc cubie right">R6</div>
        <div class="rbr cubie right">R9</div>
        <div class="lbl cubie left">L3</div>
        <div class="lbc cubie left">L6</div>
        <div class="lbr cubie left">L9</div>

        <div class="dtl cubie down">D1</div>
        <div class="dcl cubie down">D2</div>
        <div class="dbl cubie down">D3</div>
        <div class="dtc cubie down">D4</div>
        <div class="dcc cubie down">D5</div>
        <div class="dbc cubie down">D6</div>
        <div class="dtr cubie down">D7</div>
        <div class="dcr cubie down">D8</div>
        <div class="dbr cubie down">D9</div>
      </div>
    </div>
  </div>
</div>