フロントエンドのインタビューでは、CSS を使用してサイコロ/麻雀のレイアウトを実装する方法をよく尋ねられます。以下の記事では、CSSを使用して3Dサイコロを作成する方法(FlexおよびGridレイアウトで3Dサイコロを実装)を紹介しますので、ご参考になれば幸いです。
この記事から学ぶことができます:
まず、6 つの側面の HTML 構造を定義します。サイコロ:
<div class="dice-box"> <div class="dice first-face"> <span class="dot"></span> </div> <div class="dice second-face"> <span class="dot"></span> <span class="dot"></span> </div> <div class="dice third-face"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> <div class="dice fourth-face"> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> </div> <div class="fifth-face dice"> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> </div> <div class="dice sixth-face"> <div class="column"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> </div> </div>
各サーフェスと各ポイントの基本スタイルを実装しましょう:
.dice { width: 200px; height: 200px; padding: 20px; background-color: tomato; border-radius: 10%; } .dot { display: inline-block; width: 50px; height: 50px; border-radius: 50%; background-color: white; }
効果は次のとおりです:
( 1 ) ポイント
HTML 構造は次のとおりです:
<div class="dice first-face"> <span class="dot"></span> </div>
最初の面を実装するには、それを水平方向と垂直方向の中央に配置するだけです:
コードは次のように実装されます:
.first-face { display: flex; justify-content: center; align-items: center; }
最初の面は次のようになります:
(2) 2ポイント
HTML 構造は次のとおりです:
<div class="dice second-face"> <span class="dot"></span> <span class="dot"></span> </div>
まず 2 番目の側の親要素をフレックス レイアウトに設定し、次の属性を追加します:
justify-content: space- between: フレックスコンテナの先頭と末尾に子要素を配置します。
.second-face { display: flex; justify-content : space-between; }
現在のポイントの位置は次のとおりです:
現時点では、最初のポイントは正しい位置、つまり左上隅にあります。 2 番目の点は右下隅にある必要があります。そこで、align-self プロパティを使用して 2 番目の点の位置を個別に調整しましょう。
align-self: flex-end: 項目を Flex コンテナの端に揃えます。
.second-face .dot:nth-of-type(2) { align-self: flex-end; }
2 番目の面は次のようになります:
(3) 3 つの点
HTML 構造は次のとおりです:
<div class="dice third-face"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div>
3 番目の辺は、2 番目の辺に別の中心点を配置することで実現できます。
.third-face { display: flex; justify-content : space-between; } .third-face .dot:nth-of-type(2) { align-self: center; } .third-face .dot:nth-of-type(3) { align-self: flex-end; }
これで 3 番目の面は次のようになります:
最初の点を右上隅に置き、3 番目の点を配置したい場合左下隅に配置するには、最初の点の align-self を flex-end に変更できます。2 番目の点は変更されず、3 番目の点を設定する必要はありません。デフォルトは左端です。
.third-face { display: flex; justify-content : space-between; } .third-face .dot:nth-of-type(1) { align-self :flex-end; } .third-face .dot:nth-of-type(2) { align-self :center; }
3 番目の面は次のようになります。
(4) 4 つのポイント
HTML 構造は次のとおりです。
<div class="dice fourth-face"> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> </div>
.fourth-face { display: flex; justify-content: space-between }
.fourth-face .column { display: flex; flex-direction: column; justify-content: space-between; }
<div class="fifth-face dice"> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> <span class="dot"></span> </div> </div>
.fifth-face { display: flex; justify-content: space-between } .fifth-face .column { display: flex; flex-direction: column; justify-content: space-between; }
.fifth-face .column:nth-of-type(2) { justify-content: center; }
(6 ) 6 つのポイントHTML 構造は次のとおりです。
<div class="dice sixth-face"> <div class="column"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> <div class="column"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> </div>
.sixth-face { display: flex; justify-content: space-between } .sixth-face .column { display: flex; flex-direction: column; justify-content: space-between; }
骰子每个面其实可以想象成一个 3 x 3 的网格,其中每个单元格代表一个点的位置:
+---+---+---+
| a | b | c |
+---+---+---+
| d | e | f |
+---+---+---+
| g | h | i |
+---+---+---+
要创建一个 3 x 3 的网格,只需要设置一个容器元素,并且设置三个大小相同的行和列:
.dice { display: grid; grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; }
这里的 fr 单位允许将行或列的大小设置为网格容器可用空间的一部分,这上面的例子中,我们需要三分之一的可用空间,所以设置了 1fr 三次。
我们还可以使用 repeat(3, 1fr) 将 1fr 重复 3 次,来代替 1fr 1fr 1fr。还可以使用定义行/列的grid-template速记属性将上述代码进行简化:
.dice { display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); }
每个面所需要定义的 HTML 就像是这样:
<div class="dice"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div>
所有的点将自动放置在每个单元格中,从左到右:
现在我们需要为每个骰子值定位点数。开始时我们提到,可以将每个面分成 3 x 3 的表格,但是这些表格并不是每一个都是我们需要的,分析骰子的六个面,可以发现,我们只需要以下七个位置的点:
+---+---+---+
| a | | c |
+---+---+---+
| e | g | f |
+---+---+---+
| d | | b |
+---+---+---+
我们可以使用grid-template-areas属性将此布局转换为 CSS:
.dice { display: grid; grid-template-areas: "a . c" "e g f" "d . b"; }
因此,我们可以不使用传统的单位来调整行和列的大小,而只需使用名称来引用每个单元格。其语法本身提供了网格结构的可视化,名称由网格项的网格区域属性定义。中间列中的点表示一个空单元格。
下面来使用grid-area属性为网格项命名,然后,网格模板可以通过其名称引用该项目,以将其放置在网格中的特定区域中。:nth-child()伪选择器允许单独定位每个点。
.dot:nth-child(2) { grid-area: b; } .dot:nth-child(3) { grid-area: c; } .dot:nth-child(4) { grid-area: d; } .dot:nth-child(5) { grid-area: e; } .dot:nth-child(6) { grid-area: f; }
现在六个面的样式如下:
可以看到,1、3、5的布局仍然是不正确的,只需要重新定位每个骰子的最后一个点即可:
.dot:nth-child(odd):last-child { grid-area: g; }
这时所有点的位置都正确了:
对于上面的 CSS,对应的 HTML分别是父级为一个p标签,该面有几个点,子级就有几个span标签。代码如下:
<div class="dice-box"> <div class="dice first-face"> <span class="dot"></span> </div> <div class="dice second-face"> <span class="dot"></span> <span class="dot"></span> </div> <div class="dice third-face"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> <div class="dice fourth-face"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> <div class="fifth-face dice"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> <div class="dice sixth-face"> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div> </div>
整体的 CSS 代码如下:
.dice { width: 200px; height: 200px; padding: 20px; background-color: tomato; border-radius: 10%; display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); grid-template-areas: "a . c" "e g f" "d . b"; } .dot { display: inline-block; width: 50px; height: 50px; border-radius: 50%; background-color: white; } .dot:nth-child(2) { grid-area: b; } .dot:nth-child(3) { grid-area: c; } .dot:nth-child(4) { grid-area: d; } .dot:nth-child(5) { grid-area: e; } .dot:nth-child(6) { grid-area: f; } .dot:nth-child(odd):last-child { grid-area: g; }
上面我们分别使用 Flex 和 Grid 布局实现了骰子的六个面,下面来这将六个面组合成一个正方体。
首先对六个面进行一些样式修改:
.dice { width: 200px; height: 200px; padding: 20px; box-sizing: border-box; opacity: 0.7; background-color: tomato; position: absolute; }
定义它们的父元素:
.dice-box { width: 200px; height: 200px; position: relative; transform-style: preserve-3d; transform: rotateY(185deg) rotateX(150deg) rotateZ(315deg); }
其中,transform-style: preserve-3d;表示所有子元素在3D空间中呈现。这里的transform 的角度不重要,主要是便于后面查看。
此时六个面的这样的:
看起来有点奇怪,所有面都叠加在一起。不要急,我们来一个个调整位置。
首先将第一个面在 Z 轴移动 100px:
.first-face { transform: translateZ(100px); }
第一面就到了所有面的上方:
因为每个面的宽高都是 200px,所以将第六面沿 Z 轴向下调整 100px:
.sixth-face { transform: translateZ(-100px); }
第六面就到了所有面的下方:
下面来调整第二面,将其在X轴向后移动 100px,并沿着 Y 轴旋转 -90 度:
.second-face { transform: translateX(-100px) rotateY(-90deg); }
此时六个面是这样的:
下面来调整第二面的对面:第五面,将其沿 X 轴的正方向移动 100px,并沿着 Y 轴方向选择 90 度:
.fifth-face { transform: translateX(100px) rotateY(90deg); }
此时六个面是这样的:
下面来调整第三面,道理同上:
.third-face { transform: translateY(100px) rotateX(90deg); }
此时六个面是这样的:
最后来调整第五面:
.fourth-face { transform: translateY(-100px) rotateX(90deg); }
此时六个面就组成了一个完整的正方体:
下面来为这个骰子设置一个动画,让它转起来:
@keyframes rotate { from { transform: rotateY(0) rotateX(45deg) rotateZ(45deg); } to { transform: rotateY(360deg) rotateX(45deg) rotateZ(45deg); } } .dice-box { animation: rotate 5s linear infinite; }
最终的效果如下:
在线体验:
3D 骰子-Flex:https://codepen.io/cugergz/pen/jOzYGyV
3D 骰子-Grid:https://codepen.io/cugergz/pen/GROMgEe
以上がCSS フレックスおよびグリッド レイアウトを使用して 3D ダイスを実装する手順を段階的に説明します (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。