一直想作一個立體的盒子,前段時間恰好看見掘金上有位朋友發了篇關於
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