一直想作一个立体的盒子,前段时间恰好看见掘金上有位朋友发了篇关于
3d
盒子的文章,看了决定本身作一下,再写一些和盒子互动的操做。这里是要作的效果,应该要翻过墙才能够访问,这里是github地址,能够直接查看代码,上边还有别的有趣的demo,这是个人博客,欢迎来访。javascript
首先看下怎么作一个静止的盒子,用到了css3
的transform
。将盒子六个面放在一个div
里,将这个div
定位好,用transform
属性改变不一样的面的朝向,再将其向前移动盒子宽度的一半,盒子就作好了。html
结构以下:css
<div class="wraper"> <div class="cube"> <div class="front">Front</div> <div class="end">End</div> <div class="left">Left</div> <div class="right">Right</div> <div class="top">Top</div> <div class="bottom">Bottom</div> </div> </div>
设置css,不熟悉transform
能够看下下边这张图,须要注意的是元素的轴是跟着元素转动而转动的,因此几个面的translateZ
属性的值都是同样的,旋转到正确的朝向而后向前平移盒子一半的宽度。 html
body, html { height: 100%; padding: 0; margin: 0; /*将border和padding绘制在设置宽高以内*/ box-sizing: border-box; overflow: hidden; } .wraper { width: 260px; height: 260px; margin: 128px auto; /*景深,能够理解为视角到3D物体的距离,设置于舞台元素上*/ perspective: 1000px; } .cube { height: 100%; width: 100%; position: relative; /*子元素继承3D效果*/ transform-style: preserve-3d; /*加上下边这句能够体现出立体感*/ /*transform: rotateX(-30deg) rotateY(-45deg);*/ } .cube>div { width: 100%; height: 100%; position: absolute; top: 0; left: 0; background-color: rgba(0, 0, 0, .8); text-align: center; line-height: 260px; color: #fff; font-size: 48px; border: 2px solid #fff; /*设置文本内容不可选*/ user-select: none; } .front { /*正面不用旋转,直接向前平移半个盒子宽*/ transform: translateZ(130px); } .end { /*向后旋转,以确保盒子上的文字朝向盒子外*/ transform: rotateY(180deg) translateZ(130px); } .top { transform: rotateX(90deg) translateZ(130px); } .bottom { transform: rotateX(-90deg) translateZ(130px); } .left { transform: rotateY(-90deg) translateZ(130px); } .right { transform: rotateY(90deg) translateZ(130px); }
下来就是鼠标拖动盒子的核心代码了,先理一下思路,鼠标拖动盒子,就是记录下盒子的角度,而后点击鼠标并拖动的时候根据鼠标移动方向和距离从新计算出盒子的旋转角度,鼠标松开时取消监听,记录盒子角度。这和我以前写的一个例子鼠标拖动div 有点类似:java
var cube = document.querySelector(".cube"), downX, downY, moveX, moveY, tempX, tempY, degX = 0, degY = 0; window.onmousedown = function (e) { e = e || event; downX = e.clientX; //获取鼠标点下去时的坐标 downY = e.clientY; window.onmousemove = function (e) { e = e || event; moveX = e.clientX - downX; //算出鼠标移动的距离 moveY = e.clientY - downY; //根据必定比例将变化反应在盒子上,改变比例5能够调节拖动的速度 tempX = degX + moveX / 5; tempY = degY - moveY / 5; cube.style.transform = "rotatex(" + tempY + "deg) rotatey(" + tempX + "deg)"; }; }; window.onmouseup = function (e) { e = e || event; degX += moveX / 5; //鼠标松开时将拖动期间改变的最终结果保存 degY += - moveY / 5; window.onmousemove = null; //取消监听 };
再加一个使用滚轮改变景深的函数,由于景深过小视角会到盒子里边,并非很好看,因此限制了一下,在景深小于300px
时将不会减少。css3
!function () { var n = 1000; var wraper = document.querySelector('.wraper'); wraper.style.perspective = n + 'px'; window.onmousewheel = function (e) { e = e || event; if (e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件 if (e.wheelDelta > 0) { //当滑轮向上滚动时减少景深 wraper.style.perspective = n - 50 + 'px'; if (n > 350) { n = n - 50; } } if (e.wheelDelta < 0) { //当滑轮向下滚动时增长景深 wraper.style.perspective = n + 50 + 'px'; n += 50; } } else if (e.detail) { //Firefox滑轮事件 if (e.detail > 0) { wraper.style.perspective = n - 50 + 'px'; if (n > 350) { n = n - 50; } } if (e.detail < 0) { wraper.style.perspective = n + 50 + 'px'; n += 50; } } }; }();
好了,到这里这个盒子看起来已经很3D
了,你能够直接在github上复制代码查看效果,我多加了一个入场动画,喜欢能够顺手点个star
。有什么建议或问题能够在博客下方留言,欢迎探讨,共同窗习。git