css3 3D魔方

本文介绍如何使用CSS3实现3D魔方布局,包括利用弹性布局优化代码,应用CSS变量简化计算,以及通过关键帧动画实现魔方旋转效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

github地址:https://github.com/lishuai336/3D-mf/tree/master/3Dmf

 

css3强大的功能让人叹为观止,我们工作中接触到的都是皮毛,要想真正提升技术跟进前端的技术发展,靠自学才是出路。不过我倒是觉得学习是一件快乐的事情,在快乐中学习会事半功倍。

最近看到了旋转的魔方小demo,便津津有味的琢磨起来,效果如图。对了,普及一下:在css3D布局中,X轴从左往右为正方向,Y轴从上往下为正方向,Z轴从屏幕里向屏幕外为正方向,另外,我还发现,rotateX(), rotateY()和rotateZ()旋转的方向都是:沿着各轴正方向逆时针旋转,也就是说rotateX(45deg)向X轴正方向看去是逆时针旋转45度,rotateY(45deg)向Y轴正方向看去是逆时针的,同样的,rotateZ(45deg)从屏幕里向屏幕外看是逆时针的。

                                                                       

通过查看源代码,在原来的基础之上进行了一些优化,每个面的9个小块我采用了display:flex弹性布局,而原来的则是全部采用绝对定位,这样代码太过繁琐。

html代码如下:

    <body>
        <div class="box">
            <div class="boxs">
                <ul class="front">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    <li>5</li>
                    <li>6</li>
                    <li>7</li>
                    <li>8</li>
                    <li>9</li>
                </ul>
                <ul class="after">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    <li>5</li>
                    <li>6</li>
                    <li>7</li>
                    <li>8</li>
                    <li>9</li>
                </ul>
                <ul class="left">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    <li>5</li>
                    <li>6</li>
                    <li>7</li>
                    <li>8</li>
                    <li>9</li>
                </ul>
                <ul class="right">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    <li>5</li>
                    <li>6</li>
                    <li>7</li>
                    <li>8</li>
                    <li>9</li>
                </ul>
                <ul class="top">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    <li>5</li>
                    <li>6</li>
                    <li>7</li>
                    <li>8</li>
                    <li>9</li>
                </ul>
                <ul class="bottom">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                    <li>4</li>
                    <li>5</li>
                    <li>6</li>
                    <li>7</li>
                    <li>8</li>
                    <li>9</li>
                </ul>
            </div>
        </div>
    </body>

在body中定义一个变量,是的,最近才知道css也可以定义变量,定义变量符号就是“--”,而使用“--”是因为$被Sass占用了,@被Less占用了,所以是为了区分它们,由于魔方的6个面我没有采用绝对定位,要想组成一个立方体,所以每个面需要向上移动(300*-n)像素,故意这么布局的,熟悉一下css变量的使用,哈哈:

body {
	--boxHeight: 300px;			/*用于计算每个面向上移动的距离*/
}

最外层div用来确定位置,在浏览器窗口中心位置显示。

/*最外层盒子*/
.box {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 300px;
	height: 300px;
	transform: translate(-50%, -50%);
}

整个魔方的样式:

.boxs {
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;				/*使被转换的子元素保留其 3D 转换:*/
	/*transform-origin: 10% 10%;*/				/*定义了观察者的视角相对于显示元素的位置*/
	/*perspective: 500px;*/					/*设置用户与元素3d空间Z平面之间的距离*/
	backface-visibility: hidden;                        /*定义当元素不面向屏幕时隐藏*/
}

接下来是每个面的通用样式:

/*六个面通用样式*/
.boxs ul{
	height: 100%;
	display: flex;                      /*开启弹性布局*/
	flex-wrap: wrap;                    /*当一行显示不下的时候,允许换行*/
	justify-content: space-between;     /*块与块之间留有相等间距,与外层容器不留间距*/
}

魔方每个面9个小块的布局样式:

/*每个面9个小块通用样式*/
.boxs ul li{
	width: calc(calc(100% / 3) - 1px);        /* calc()是css函数,用于动态计算数值*/
	height: calc(calc(100% / 3) - 1px);
	text-align: center;
	font-size: 20px;
	line-height: 99px;
	border-radius: 5px;
}

前面:由于魔方边长设置的300px,Z轴默认的基点位置是在0处,所以要拼成魔方,前面需向前移动150px:

.boxs .front{
	transform: translateZ(150px);
}
.boxs .front li{
	background-color: #0f0;        /*前面小块背景色*/
}

这样第一个面的布局就完成了,如图:

 

后面:向Z轴负方向移动150px,由于我没有采用绝对定位,在布局中默认是这样的,所以要往上移动一个面的高度,另外,由于是后面,所以要沿着Y轴旋转180度:

.boxs .after{
	transform: translateZ(-150px) translateY(calc(var(--boxHeight) * -1)) rotateY(180deg);
}
.boxs .after li{
	background-color: #00f;
}

这时给整个魔方沿着X轴和Y轴旋转45度看下效果,此时前后面布局完成:

.boxs {
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;				/*使被转换的子元素保留其 3D 转换:*/
	/*transform-origin: 10% 10%;*/				/*定义了观察者的视角相对于显示元素的位置*/
	/*perspective: 500px;*/					    /*设置用户与元素3d空间Z平面之间的距离*/
	backface-visibility: hidden;                /*定义当元素不面向屏幕时隐藏*/
	transform: rotateY(45deg) rotateX(45deg);
}

 

剩下4个面的布局同理,每个面都需要往上移动(300 * -n)px,左右两面分别沿X轴移动-150px和150px,沿着Y轴旋转-90deg和90deg,上下两面分别沿着Y轴移动150px和-150px,沿着X轴旋转90deg和-90deg:

/*左*/
.boxs .left{
	transform: translateX(-150px) translateY(calc(var(--boxHeight) * -2)) rotateY(-90deg);
}
.boxs .left li{
	background-color: #f00;
}
/*右*/
.boxs .right {
	transform: translateX(150px) translateY(calc(var(--boxHeight) * -3)) rotateY(90deg);
}
.boxs .right li{
	background-color: #ff0;
}
/*上*/
.boxs .top {
	transform: translateY(calc(var(--boxHeight) * -4 - 150px)) rotateX(90deg);
}
.boxs .top li {
	background-color: #f0f;
}
/*下*/
.boxs .bottom{
	transform: translateY(calc(var(--boxHeight) * -5 + 150px)) rotateX(-90deg);
}
.boxs .bottom li{
	background-color: #0ff;
}

再看下布局效果,此时就完成魔方3D布局了:

最后让它动起来:

@keyframes change {
	0% {
		transform: rotateX(0deg) rotateY(0deg);
	}
	33% {
		transform: rotateX(120deg) rotateY(240deg);
	}
	66% {
		transform: rotateX(240deg) rotateY(480deg);
	}
	100% {
		transform: rotateX(360deg) rotateY(720deg);
	}
}
.boxs {
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;				/*使被转换的子元素保留其 3D 转换:*/
	/*transform-origin: 10% 10%;*/				/*定义了观察者的视角相对于显示元素的位置*/
	/*perspective: 500px;*/						/*设置用户与元素3d空间Z平面之间的距离*/
	animation: change 10s linear infinite;
	backface-visibility: hidden;
}

最后添加一个鼠标悬浮,停止旋转,用到的是animation-play-state属性:

.box:hover .boxs{
	animation-play-state: paused;
}

这样就完成啦,有点小激动呢,不过好像我做的动态图没有看到鼠标...哈哈:

 

添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值