2016年淘宝发出一封造物节的H5邀请函,风靡朋友圈.我们发现不需要通过建模、webgl等技术,仅通过css3与js我们也能实现3D场景与视角.我们经常使用css3中的transform对元素进行3d变换,实现一些长方体等.就从这个角度出发,我们一点点实现3D场景.
第1步:先用css3制作长方体
dom元素在做transform变形时是按照x,y,z轴来做参照,初始状态元素做rotate旋转时,默认以z轴为中心旋转.z轴垂直于屏幕,如下图:
为了方便查看3d效果,我们先准备一个容器,并且给它设置三个属性:
1.先设置容器transform-style:preserve-3d,表示容器内部以3D空间呈现。
2.再设置容器的perspective:100px;(景深),可以理解为用户和屏幕的距离,初始时元素位置是紧贴屏幕的.若元素此时往translateZ负方向移动,则看到的元素越来越小。若元素往translateZ正方向移动,则看到的元素越来越大,当这个正值等于我们设置的perspective时,元素将消失,此时的情况就是元素运动到和我们的视点同一平面,视线刚好穿过了元素。
3.还需要设置容器的perspective-origin:10px 10px;(视点),默认我们从元素的正中心看向它,设置视点就是设置我们从哪个点看向元素。
为了制作正方体,我们在容器内准备六个颜色不同的平面.初始时6个平面是重叠的,只能看到一个平面,我们旋转并移动第1个平面,让它和初始的平面垂直,并且设置我们的视点从容器右下方看向容器(注意transform执行时写在后面的先执行)
#box {position: relative;width: 10px;height: 10px;margin: 200px auto;transform-style:preserve-3d;perspective:300px;perspective-origin:100px 200px;} #box div {position: absolute;left: 50%;top: 50%;margin: -50px 0 0 -50px;width: 100px;height: 100px;text-align: center;font-size: 26px; line-height: 100px;} #box div:nth-of-type(1) {background: yellow;transform:translateX(-50px) translateZ(-50px) rotateY(-90deg); } #box div:nth-of-type(2) {background: red;} #box div:nth-of-type(3) {background: gray; } #box div:nth-of-type(4) {background: blue; } #box div:nth-of-type(5) {background: #FFCC00;} #box div:nth-of-type(6) {background: green;} ----------------------------------------------------- <div id="box"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>
接着我们依次transform其余四个面,让6个平面拼成正方体,且还是在右下方的视角看向正方体.(注意控制角度使元素正面朝外)
#box div:nth-of-type(1) {background: yellow;transform:translateX(-50px) translateZ(-50px) rotateY(-90deg);} /*左面*/ #box div:nth-of-type(2) {background: red;transform:translateZ(-50px) translateY(-50px) rotateX(90deg);} /*上面*/ #box div:nth-of-type(3) {background: gray;transform:translateZ(-50px) translateY(50px) rotateX(-90deg); } /*下面*/ #box div:nth-of-type(4) {background: blue;transform:translateX(50px) translateZ(-50px) rotateY(90deg);} /*右面*/ #box div:nth-of-type(5) {background: #FFCC00;transform:translateZ(-100px) rotateY(180deg);} /*后面*/ #box div:nth-of-type(6) {background: green;} /*前面,初始面*/
第2步:正方体内部视角的制作和修正
此时我们尝试让正方体一直向我们的方向移动.我们需要再套一个容器方便整体移动,并以中心点为基准.当新容器的translateZ超过我们设置的景深值时,就像上面提到的,我们的视线穿透了初始面上的元素,从而看到了正方体的内部。
我们已经可以控制视角进出一个盒子内部了.但此时进入盒子后看到的是元素的背面,是反向的.接下来我们设置backface-visibility:hidden;隐藏元素背面,此时元素只有正面可以被看到,从元素背面是看不到元素的.当进入正方体内时,由于正方体内部显示的全部是元素背面,所以元素都隐藏了.
#box div {position: absolute;left: 50%;top: 50%;margin: -50px 0 0 -50px;width: 100px;height: 100px;text-align: center;font-size: 26px; line-height: 100px; backface-visibility: hidden;}
接着我们让每两个对立的面互换位置,以此保证了每个面外正面朝内,背面朝外,这样可以看到正方体内部的面,外部的面看不到.
#box div:nth-of-type(1) {background: yellow;transform:translateX(50px) translateZ(-50px) rotateY(-90deg);} /*左面*/ #box div:nth-of-type(2) {background: red;transform:translateZ(-50px) translateY(50px) rotateX(90deg);} /*上面*/ #box div:nth-of-type(3) {background: gray;transform:translateZ(-50px) translateY(-50px) rotateX(-90deg); } /*下面*/ #box div:nth-of-type(4) {background: blue;transform:translateX(-50px) translateZ(-50px) rotateY(90deg);} /*右面*/ #box div:nth-of-type(5) {background: #FFCC00;transform:rotateY(180deg);} /*后面*/ #box div:nth-of-type(6) {background: green;transform:translateZ(-100px)} /*前面*/ a{ position: relative; z-index: 10; color: #000;}
此时我们便可以在正方体中看到所有正面,并且方便调试了.为了模拟3D视角,我们把视角固定在正方体的中心,并且让正方体以自身中心点旋转,我们便可以浏览这个小空间了.transform-origin:50% 50% 100px;用来设置元素运动的中心点.
#box {position: relative;width: 10px;height: 10px;margin: 300px auto;transform-style:preserve-3d;perspective:300px;} #box div {position: absolute;left: 50%;top: 50%;margin: -50px 0 0 -50px;width: 100px;height: 100px;text-align: center;font-size: 26px; line-height: 100px; backface-visibility: hidden;} #wrap{ display: block; transform:rotateY(0deg) translateZ(350px);transform-style:preserve-3d;perspective:300px;transform-origin: 50% 50% 300px;}
最终我们制作了一个正方体,并且可以浏览它内部的空间.当然为了兼容更多视角角度的移动,还需要做很多兼容处理.在此基础上我们加入touch操作,封装动画,再用全景照片替换6个面上的文字,可以实现全景看房的效果.点击查看Demo(移动端)
最后的Demo 地址挂了
3q,可以了