大家好,flex布局是大家前端页面开发时常用的布局之一,好多小伙伴在面试的时候也常被问到,类似于如何做一个骰子的四点布局的问题,今天我们通过这个小练习来熟悉一下flex布局的妙用吧!
效果图:
还是挺有意思的对吧!最后附上完整源码!
首先我们先复习下flex弹性盒子吧!
通常我们通过给某个元素设置display:flex;
就可以将该元素转为块级弹性盒子,display:inline-flex;
是行内的弹性盒子。容器默认存在两根交叉轴:水平的主轴(main axis)和垂直的交叉轴(侧轴)(cross axis),两根轴永远垂直。
flex的几个属性:
flex-direction 属性 决定主轴的方向(即项目的排列方向)
flex-direction: row(默认水平) | row-reverse | column(纵向) | column-reverse;
flex-wrap 属性 定义子元素是否换行显示
flex-wrap: nowrap(不换行) | wrap(换行) | wrap-reverse;(反向换行)
justify-content属性 定义了项目在主轴()上的对齐方式
justify-content: flex-start | flex-end | center | space-between | space-around;
align-items 属性 定义项目在侧轴(单行)上如何对齐
align-items: flex-start | flex-end | center | baseline | stretch(默认值);
align-content 属性 定义了多根轴线的对齐方式
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
flex-flow
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap;
我们都知道,骰子六个面分别刻着1到6六个小圆点。所以第一步我们得先准备一个容器,将这六个面及上面的圆点绘制出来,下面上代码:
<!--容器盒子以及六个面-->
<div class="container">
<div class="side"></div>
<div class="side"></div>
<div class="side"></div>
<div class="side"></div>
<div class="side"></div>
<div class="side"></div>
</div>
再来点css样式:
/*给父元素flex布局,六个面居中*/
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container .side {
width: 100px;
height: 100px;
background-color: rgb(235, 230, 230);
border: 1px solid #000;
}
如图,六个面容器这就准备好了。
下面开始上点,如1点:
<div class="side">
<div class="item"></div>
</div>
/*给父盒子设置flex,两条主轴居中(center),远点就位于中心了*/
.container .side:nth-child(1) {
display: flex;
justify-content: center;
align-items: center;
}
.circle {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rgb(246, 1, 1);
/* 圆点上下内阴影,凸显出立体感 */
box-shadow: inset 0 3px rgb(158, 3, 3), inset 0 -2px rgb(158, 3, 3);
}
2点:
<div class="side">
<div class="item"></div>
<div class="item"></div>
</div>
.container .side:nth-child(2) {
/* 让两个圆点分布在左右两侧 */
justify-content: space-between;
}
.container .side:nth-child(2) .circle:nth-child(2) {
/* 让第二个圆点侧轴方向倒序开始 */
align-self: flex-end;
}
感觉小圆点太靠边缘了,我们直接给每个面(side)加上padding: 10px;
就好了
3点:
<div class="side">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
.container .side:nth-child(3) .circle:nth-child(1) {
align-self: flex-start;
}
/*中间圆点居中*/
.container .side:nth-child(3) .circle:nth-child(2) {
align-self: center;
}
.container .side:nth-child(3) .circle:nth-child(3) {
align-self: flex-end;
}
456三个点我们得将其再次划分,4和6点分为两部分,4点每部分占两个圆点,6点每部分占3个,5点则需分三部分,左右占2中间占1
如四点:
<div class="side">
<div class="item">
<div class="circle"></div>
<div class="circle"></div>
</div>
<div class="item">
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
.container .side:nth-child(4) .item {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.container .side:nth-child(4) {
justify-content: space-between;
}
5点:
<div class="side">
<div class="item">
<div class="circle"></div>
<div class="circle"></div>
</div>
<div class="item">
<div class="circle"></div>
</div>
<div class="item">
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
.container .side:nth-child(5) .item {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.container .side:nth-child(5) .item:nth-child(2) {
justify-content: center;
}
.container .side:nth-child(5) {
justify-content: space-between;
}
6点:
<div class="side">
<div class="item">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
<div class="item">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
</div>
.container .side:nth-child(6) .item {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.container .side:nth-child(6) {
justify-content: space-between;
}
此时页面完整效果如下:
最后,我们通过给容器盒子(container)添加transform-style: preserve-3d;
开启3d模式,再通过transform: translate()
调整各个面的位置,以及加个小动画就OK了!
完整源码如下:
<div class="container">
<div class="side"></div>
<div class="side"></div>
<div class="side"></div>
<div class="side">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="side">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="side">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<button class="btn">停止旋转</button>
* {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
background-image: linear-gradient(45deg, rgb(244, 199, 207), rgb(115, 190, 237));
perspective: 700px;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
transform-style: preserve-3d;
animation: rot 0.5s linear infinite;
}
.container .side {
position: absolute;
width: 100px;
height: 100px;
background-color: rgb(235, 230, 230);
box-shadow: 0 0 10px rgb(196, 192, 192);
display: flex;
padding: 10px;
box-sizing: border-box;
}
.circle {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rgb(246, 1, 1);
/* 圆点上下内阴影,凸显出立体感 */
box-shadow: inset 0 3px rgb(158, 3, 3), inset 0 -2px rgb(158, 3, 3);
}
.container .side:nth-child(1) {
justify-content: center;
align-items: center;
}
.container .side:nth-child(2),
.side:nth-child(3),
.side:nth-child(4),
.side:nth-child(5),
.side:nth-child(6) {
justify-content: space-between;
}
.container .side:nth-child(2) .circle:nth-child(1),
.side:nth-child(3) .circle:nth-child(1) {
align-self: flex-start;
}
.container .side:nth-child(2) .circle:nth-child(2),
.side:nth-child(3) .circle:nth-child(3) {
align-self: flex-end;
}
.container .side:nth-child(3) .circle:nth-child(2) {
align-self: center;
}
.container .side:nth-child(4) .item,
.side:nth-child(5) .item,
.side:nth-child(6) .item {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.container .side:nth-child(5) .item:nth-child(2) {
justify-content: center;
}
.container .side:nth-child(1) {
transform: translateZ(-50px);
}
.container .side:nth-child(2) {
transform: rotateX(90deg) translateZ(-50px);
}
.container .side:nth-child(3) {
transform: rotateY(90deg) translateZ(-50px);
}
.container .side:nth-child(4) {
transform: rotateX(90deg) translateZ(50px);
}
.container .side:nth-child(5) {
transform: rotateY(90deg) translateZ(50px);
}
.container .side:nth-child(6) {
transform: translateZ(50px);
}
.btn {
position: absolute;
right: 50px;
top: 50px;
width: 100px;
height: 50px;
background-image: linear-gradient(90deg, rgb(236, 162, 133), rgb(237, 127, 143));
border: 0px;
border-radius: 5px;
}
.btn:hover {
box-shadow: 0 0 20px rgb(211, 180, 133);
border: 1px solid rgb(92, 142, 234);
}
/*旋转动画*/
@keyframes rot {
from {
transform: rotateY(0deg) rotateZ(0deg);
}
to {
transform: rotateY(360deg) rotateZ(360deg);
}
}
let containerBox = document.querySelector('.container')
let btn = document.querySelector('.btn')
let childBoxLen = containerBox.children.length
let flag = true
for (let i = 0; i < childBoxLen; i++) {
addChildNode(containerBox, i)
}
//添加小圆点
function addChildNode(node, len) {
let cLen = node.children[len].children.length
if (len >= 3) {
if (len === 4) {
for (let i = 0; i < 3; i++) {
if (i !== 1) {
createCircle(node.children[len].children[i])
}
createCircle(node.children[len].children[i])
}
} else {
let c = Math.floor((len + 1) / cLen)
for (let i = 0; i < 2; i++) {
for (let j = 0; j < c; j++) {
createCircle(node.children[len].children[i])
}
}
}
} else {
for (let i = 0; i < len + 1; i++) {
createCircle(node.children[len])
}
}
}
//生成小圆点
function createCircle(node) {
let circle = document.createElement('div')
circle.classList.add('circle')
node.appendChild(circle)
}
//控制动画暂停播放
btn.addEventListener('click', (e) => {
flag = !flag
console.log(e.target)
btn.innerHTML = flag ? '停止旋转' : '开始旋转'
containerBox.style.animationPlayState = flag ? '' : 'paused'
})
我这里是用一些比较粗糙的js代码生成的小圆点,大家也可以像开始介绍步骤那样直接在html里面插入小圆点代码,不用js生成.
以上就是完整内容,感谢大家观看,有什么建议小伙伴们可以评论留言哦!
暂无评论内容