使用 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
属性(如 translate
、scale
、rotation
)组合成一个矩阵。但是由于 matrix3d()
需要 16 个参数,所以我不会短很多。
获取 matrix3d
参数的简单方法是 select 浏览器检查器中的元素并查看计算值。
困难的方法是自己计算值。
要计算数值,首先要了解每个数值的含义。例如,您可以在 MDN 中查找它们。
您会注意到,在使用 translate3d
和 rotationY
时,您需要调整矩阵上的以下值(就像您的 Codepen 中的 cubie L8):
cos(rot) 0 sin(rot) tx
0 1 0 ty
-sin(rot) 0 cos(rot) tz
0 0 0 1
tx
、ty
、tz
分别是 translateZ
、translateY
和 translateX
.
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>
我一直在探索在 CSS 中使用 perspective
来创建一个立方体,希望最终我可以为它制作动画。
目前,每个面上的每个方块都是绝对定位的 CSS 3D 变换,但我想知道是否可以通过使用 transform: matrix3d()
来减少我编写的代码量?
我找不到对我有意义的 transform: matrix3d()
解释,所以我不确定如何使用它,或者它是否真的是我要找的东西。
这是我目前所拥有的 CodePen - 不幸的是它目前是静态的,所以它不会旋转,但是有 6 个面。
简答:不,使用matrix3d
不会减少太多代码量。
长答案:您可以将多个 transform
属性(如 translate
、scale
、rotation
)组合成一个矩阵。但是由于 matrix3d()
需要 16 个参数,所以我不会短很多。
获取 matrix3d
参数的简单方法是 select 浏览器检查器中的元素并查看计算值。
困难的方法是自己计算值。
要计算数值,首先要了解每个数值的含义。例如,您可以在 MDN 中查找它们。
您会注意到,在使用 translate3d
和 rotationY
时,您需要调整矩阵上的以下值(就像您的 Codepen 中的 cubie L8):
cos(rot) 0 sin(rot) tx
0 1 0 ty
-sin(rot) 0 cos(rot) tz
0 0 0 1
tx
、ty
、tz
分别是 translateZ
、translateY
和 translateX
.
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>