当前位置: 首页 > 科技观察

具有Flex和网格布局的3D骰子!_0

时间:2023-03-19 12:30:17 科技观察

大家好,我叫CUGGZ。在前端面试中,经常会被问到如何使用CSS实现骰子/麻将布局。今天我们将使用CSS制作一个3D骰子,通过这篇文章我们可以学习;使用transform实现3D形状;为3D骰子实现旋转动画;使用Flex布局实现骰子布局;使用Grid布局实现骰子布局。1、使用Flex布局实现六面首先定义骰子六面的HTML结构:

下面是实现每个面每个点的基本样式:.dice{width:200px;高度:200px;填充:20px;背景色:番茄;border-radius:10%;}.dot{display:inline-block;宽度:50px;高度:50px;边界半径:50%;white;}效果如下:(1)一个点的HTML结构如下:实现第一个面,只需要水平和垂直居中即可:justify-content:center:将点与主轴中心对齐(水平)align-items:center:将点与横轴(垂直)的中心对齐。代码实现如下:.first-face{display:flex;证明内容:居中;align-items:center;}现在第一个面是这样的:(2)两点的HTML结构如下:首先将第二面的父元素设置为flex布局,并添加如下属性:justify-content:space-between:将子元素放在开头和flex容器的末尾。.second-face{显示:flex;justify-content:space-between;}现在点的位置如下:此时第一个点在正确的位置:左上角。第二点需要在右下角。那么,我们单独使用align-self属性来调整第二个点的位置:align-self:flex-end:将item对齐到flex容器的尾部。.second-face.dot:nth-of-type(2){align-self:flex-end;}现在第二张脸是这样的:(3)三点HTML结构如下:可以传在第二面放置另一个中心点以实现第三面。align-self:flex-end:将项目对齐到flex容器的末尾。align-self:center:将项目对齐到弹性容器的中间。.third-face{显示:flex;调整内容:空间之间;}.third-face.dot:nth-of-type(2){align-self:center;}.third-face.dot:nth-of-type(3){align-self:flex-end;}现在第三边是这样的:如果你想让第一个点在右上角,第三个点在左下角,你可以把第一个点的align-self放在改为flex-end,第二点不变,第三点不用设置,默认在最左边:.third-face{display:flex;对齐内容:空间之间;}.third-face.dot:nth-of-type(1){align-self:flex-end;}.third-face.dot:nth-of-type(2){align-self:center;}现在第三面是这样的:(4)四个点的HTML结构如下:面对四个点,可以分为两行,每行包含两列。一行将在flex-start处,另一行在flex-end处。并添加justify-content:space-between将其放置在骰子的左右两侧。.fourth-face{显示:flex;justify-content:space-between}接下来需要分别对points的两列进行布局:设置column为flexlayout;将flex-direction设置为column,以便点垂直放置在方向上将justify-content设置为space-between,这将使第一个点在顶部,第二个点在底部。.fourth-face.column{显示:flex;弹性方向:列;justify-content:space-between;}现在第四张面是这样的:(5)五点的HTML结构如下:第五面和第四面的区别side是中间多了一个点。所以,在第四面的基础上,可以在中间加一列,样式如下:.fifth-face{display:flex;证明内容:空间之间}.fifth-face.column{显示:flex;弹性方向:列;justify-content:space-between;}现在第五张脸是这样的:需要调整中间点,可以设置justify-content为center使其垂直居中:.fifth-face.column:nth-of-type(2){justify-content:center;}现在第五面是这样的:(6)六个点的HTML结构如下:第六个的布局surface和第四层两者几乎一模一样,只是每一列多了一个元素。布局实现如下:.sixth-face{display:flex;证明内容:空间之间}.sixth-face.column{显示:flex;弹性方向:列;justify-content:space-between;}现在第六面是这样的:2.使用Grid布局实现六面。骰子的每一面实际上可以想象成一个3x3的格子,其中每个格子代表一个点的表格位置:+---+---+---+|一个|乙|c|+---+---+---+|d|电子|f|+---+---+---+|克|小时|i|+---+---+---+要创建一个3x3的网格,只需设置一个容器元素并设置三个相同大小的行和列:.dice{display:grid;网格模板行:1fr1fr1fr;grid-template-columns:1fr1fr1fr;}这里的fr单元允许设置行或列的大小为grid容器可用空间的一部分。在上面的例子中,我们需要三分之一的可用空间,所以我们将1fr设置了三次,我们可以使用repeat(3,1fr)将1fr重复3次,而不是1fr1fr1fr。上面的代码也可以使用定义行/列的网格模板速记属性来简化:.dice{display:grid;grid-template:repeat(3,1fr)/repeat(3,1fr);}每个面都需要定义的HTML如下所示:所有的点都会自动放在每个单元格中,从左到右:现在我们需要确定每个骰子值的点数。一开始我们提到每个人脸可以分成3x3的表格,但并不是所有这些表格都是我们需要的。分析骰子的六个面,我们可以发现,我们只需要以下七个位置的点数:+---+---+---+|a||c|+---+---+---+|e|g|f|+---+---+---+|d||b|+---+---+---+我们可以将此布局转换为使用grid-template-areas属性的CSS:.dice{display:grid;grid-template-areas:"a.c""egf""d.b";}因此,我们可以简单地按名称引用每个单元格,而不是使用传统单位来调整行和列的大小。语法本身提供了网格结构的可视化,名称由网格项的grid-area属性定义。中间列中的点代表一个空单元格。让我们使用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;}这时候,所有points的位置都是正确的:对于上面的CSS,对应的HTML是parentlevel是一个div标签,surface有几个点,childlevel有几个span标签。代码如下:整体CSS代码如下:.dice{width:200px;高度:200px;填充:20px;背景颜色:番茄;边界半径:10%;显示:网格;网格模板:重复(3、1fr)/重复(3、1fr);grid-template-areas:"a.c""egf""d.b";}.dot{display:inline-block;宽度:50px;高度:50px;边界半径:50%;背景颜色:白色;}.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;}3.上面实现3D骰子我们分别用Flex和Grid布局实现了骰子的六个面,下面将六个面组合成一个立方体首先对六个边做一些样式修改:.dice{width:200px;高度:200px;填充:20px;框大小:边框框;不透明度:0.7;背景色:番茄;position:absolute;}定义它们parentelement:.dice-box{width:200px;高度:200px;位置:相对;变换样式:保留3d;transform:rotateY(185deg)rotateX(150deg)rotateZ(315deg);}其中,transform-style:preserve-3d;指示所有子元素都在3D空间中呈现。这里变换的角度并不重要,主要是为了后面的观看。此时,六张面孔是这样的:看起来有些奇怪,所有的面孔都叠加在了一起。别着急,让我们一一调整位置。先将第一个面在Z轴上移动100px:.first-face{transform:translateZ(100px);}第一个面在所有面之上:因为每个面的宽高都是200px,所以第六个面调整面沿Z轴向下100px:.sixth-face{transform:translateZ(-100px);}第六个面在所有面的下方:让我们调整第二个面并沿X轴向后移动100px,并旋转-90度沿Y轴:.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);}此时,六个面组成了一个完整的立方体:让我们为骰子设置一个动画,让它旋转:@keyframesrotate{from{transform:rotateY(0)rotateX(45deg)rotateZ(45deg);}to{变换:旋转Y(360deg)rotateX(45deg)rotateZ(45deg);}}.dice-box{animation:rotate5slinearinfinite;}最终效果如下:在线体验:3DDice-Flex:https://codepen.io/cugergz/pen/jOzYGyV3DDice-Grid:https://codepen.io/cugergz/pen/GROMgEe