最近在 http://algoexpert.io/ 上看到一個非常好玩的東西。
剛開始的時候,我還要以爲要用到什麼 JS 庫來實現的,打開控制檯研究了一下,原來用 CSS 就可以實現了,好吧,算我孤陋寡聞了,哈哈。於是,寫篇博客記錄一下吧。
6 個面
首先,在 HTML 弄 6 個面。
<div class="cube-container">
<div class="cube-faces">
<div class="cube-face cube-face-front">
<img src="https://yanhaixiang.com/cube/images/js.png" alt="js">
</div>
<div class="cube-face cube-face-back">
<img src="https://yanhaixiang.com/cube/images/python.png" alt="python">
</div>
<div class="cube-face cube-face-top">
</div>
<div class="cube-face cube-face-bottom">
</div>
<div class="cube-face cube-face-left">
<img src="https://yanhaixiang.com/cube/images/golang.png" alt="golang">
</div>
<div class="cube-face cube-face-right">
<img src="https://yanhaixiang.com/cube/images/cpp.png" alt="cpp">
</div>
</div>
</div>
非常簡單,container 作爲正方體容器,cube-faces 作爲 6 個面的容器,剩下的 div 就是 6 個面,裏面放一個 img。
效果就是一列排下來:
集合 6 個面
第二步,就是將這 6 個面堆疊在一起。很簡單,只要 .cube-faces 設置 position: relative,然後 .cube-face 設置 position: absolute 就可以使得 6 個面都脫離文檔流疊在一起了。
.cube-faces {
position: relative;
width: 300px;
}
.cube-face {
position: absolute;
height: 300px;
width: 300px;
outline: 1px solid #02203c;
box-shadow: inset 0 0 100px #02203c;
background-color: #3e526a;
opacity: 0.75;
}
.cube-face img {
width: 100%;
height: 100%;
}
旋轉平面
現在還是一個平面結構,下面將這 6 個面通過 transform: rotate 來做旋轉使得其像個正方體。
.cube-face.cube-face-front {
transform: translateZ(150px);
}
.cube-face.cube-face-back {
transform: translateZ(-150px) rotateY(180deg);
}
.cube-face.cube-face-top {
transform: rotateX(-90deg) translateY(-150px);
transform-origin: top center;
}
.cube-face.cube-face-bottom {
transform: rotateX(90deg) translateY(150px);
transform-origin: bottom center;
}
.cube-face.cube-face-left {
transform: rotateY(270deg) translateX(-150px);
transform-origin: left center;
}
.cube-face.cube-face-right {
transform: rotateY(-270deg) translateX(150px);
transform-origin: top right;
}
很遺憾,出來的效果還是一個“平面”。
首先,這 6 個面其實已經轉成了正方體了,但是因爲我們目光只朝着一個面看,所以看起來還是二維的。但是也不對呀,如果已經變成立方體,那我們看到的應該是 JS 這一面而不是 Python 這面呀,Python 不是旋轉到後面了麼?
雖然 Python 是作爲後背面,但是在 HTML 裏,python 的 div 在 JS 的 div 之後,所以優先顯示 Python。
爲了去掉 HTML 的順序影響,可以在 .cube-faces 添加:
.cube-faces {
position: relative;
width: 300px;
transform-style: preserve-3d; /* 3D */
}
現在立方體的 JS 面就朝着我們來了:
立起來
下面隆重介紹 CSS 的 perspective 屬性,可以把它理解爲我們的目光放在哪裏。剛剛說到,我們看到二維面是因爲我們目光死死盯着一個面,所以我們只需要將目光往上擡一下,從上往下看整個立方體,立方體就“立體”起來了。
/*將立方體放中間*/
body {
display: flex;
align-items: center;
justify-content: center;
}
.cube-container {
margin-top: 200px;
perspective: 800px; /* 目光延長線 */
perspective-origin: 50% 100px; /* 目光位置水平居中,往上擡 100px */
}
開始有那味了。
轉起來
下一步,爲了讓立方體有動感一點,定義一個 @keyframes 動畫:
@keyframes spin { /* Y軸旋轉 */
0% {
transform: rotateY(0);
}
100% {
transform: rotateY(360deg);
}
}
.cube-faces {
position: relative;
width: 300px;
transform-style: preserve-3d;
animation: spin 10s infinite linear; /*動畫*/
}
加點陰影
現在的立方體已經很立體了,但是總感覺很假的樣子,這是因爲缺少陰影的原因。我們要以在底部那個 div 加點小陰影:
.cube-face.cube-face-bottom {
transform: rotateX(90deg) translateY(150px);
transform-origin: bottom center;
box-shadow: 0 0 100px #000; /*陰影*/
}
大功告成!