使用 matrix3D 创建立方体,作为多个变换的替代方法?

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

我一直在探索在 CSS 中使用 perspective 来创建一个立方体,希望最终我可以为它制作动画。

目前,每个面上的每个方块都是绝对定位的 CSS 3D 变换,但我想知道是否可以通过使用 transform: matrix3d() 来减少我编写的代码量?

我找不到对我有意义的 transform: matrix3d() 解释,所以我不确定如何使用它,或者它是否真的是我要找的东西。

这是我目前所拥有的 CodePen - 不幸的是它目前是静态的,所以它不会旋转,但是有 6 个面。

简答:不,使用matrix3d不会减少太多代码量。

长答案:您可以将多个 transform 属性(如 translatescalerotation)组合成一个矩阵。但是由于 matrix3d() 需要 16 个参数,所以我不会短很多。

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

要计算数值,首先要了解每个数值的含义。例如,您可以在 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 

txtytz 分别是 translateZtranslateYtranslateX.

rot 是弧度的 rotationY

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

cos(1.57) = 0.00079632671

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