我使用了jquery編寫交互的旋轉,由於初學因此不太承受,還請見諒。樣式我是寫stylus編碼,自動生成css。css
先放上一張效果圖
html
我將其分紅三部分。第一部分是正方體部分(SVG
),第二部分是svg
中的路徑動畫了(animateMotion
+ jQuery
),第三部分則是交互旋轉(jQuery
)。jquery
作一個正方體git
個人思路是用六塊svg
正方形畫板經過css
屬性旋轉和平移來構成正方體。github
html
代碼:數組
<div class="page"> <div class="state"> <!-- 定位--> <div class="container"> <!--旋轉--> <!-- 前 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="front"> <rect class="rect"></rect> </svg> <!-- 後 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="behind"> <rect class="rect "></rect> </svg> <!-- 左 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="left"> <rect class="rect "></rect> </svg> <!-- 右 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="right"> <rect class="rect "></rect> </svg> <!-- 上 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="top"> <rect class="rect "></rect> </svg> <!-- 下 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bottom"> <rect class="rect "></rect> </svg> </div> </div> </div>
stylus
代碼svg
html margin 0 padding 0 height 100% width 100% body height 100% width 100% .page .state height 300px width 300px position absolute top 50% left 50% transform translate(-50%,-50%)//修正位置 .container transform-style preserve-3d position relative height 300px width 300px transform rotateX(0deg) rotateY(0deg) svg position absolute height 300px width 300px stroke-width 5px stroke brown fill transparent //填充用透明 .rect height 300px width 300px .top transform rotateX(90deg) translateZ(150px) .bottom transform rotateX(-90deg) translateZ(150px) .left transform rotateY(-90deg) translateZ(150px) .right transform rotateY(90deg) translateZ(150px) .front transform rotateY(0deg) translateZ(150px) .behind transform rotateY(180deg) translateZ(150px)
一般有兩種方式來構建一個立方體
第一種:先平移再旋轉。優勢是不準太強的空間構造能力,寫起來比較簡單。缺點就是:代碼數會多一些,須要在平移後設置旋轉基點。替換一下樣式就行。模塊化
.top fill blue transform-origin: bottom transform translateY(-200px) rotateX(90deg) .bottom fill red transform-origin:top transform translateY(200px) rotateX(-90deg) .left fill green transform-origin: right transform translateX(-200px) rotateY(-90deg) .right fill black transform-origin: left transform translateX(200px) rotateY(90deg) .front fill grey transform translateZ() .behind fill pink transform translateZ(-200px)
第二種:先旋轉再平移。這個的特色就是與上面的相反了。(我使用的是這種)
兩種生成立方體的原理看下圖
第一種
第二種
以上就是兩種構創建方體的方法大體原理了wordpress
路徑動畫我是經過在相鄰兩個面上一個動畫結束的位置和下一個動畫起始位置重合,
下一個動畫起始的延時設置爲以前全部動畫的動畫時間,作到視覺認爲路線是鏈接起來的。
先上代碼:函數
<div class="state"> <!-- 定位--> <div class="container"> <!--旋轉--> <!-- 前 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="front"> <rect class="rect"></rect> <circle x="0" y="0" r="5" stroke="none" fill="red"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#frontY"></mpath> </animateMOtion> </circle> <circle x="0" y="0" r="5" stroke="none" fill="blue"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#frontX"></mpath> </animateMOtion> </circle> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m150.75,0.75l0,300" id="frontY" /> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m300,150c-300,0 -300,0 -300,0" id="frontX" /> </svg> <!-- 後 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="behind"> <rect class="rect "></rect> <circle x="0" y="0" r="5" stroke="none" fill="red"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#behindY"></mpath> </animateMOtion> </circle> <circle x="0" y="0" r="5" stroke="none" fill="blue"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#behindX"></mpath> </animateMOtion> </circle> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m150,300c0,0 1,-300 0,-300" id="behindY" /> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m300,150c-300,0 -300,0 -300,0" id="behindX" /> </svg> <!-- 左 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="left"> <rect class="rect "></rect> <circle x="0" y="0" r="5" stroke="none" fill="blue"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#leftX"></mpath> </animateMOtion> </circle> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m300,150c-300,0 -300,0 -300,0" id="leftX" /> </svg> <!-- 右 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="right"> <rect class="rect "></rect> <circle x="0" y="0" r="5" stroke="none" fill="blue"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#rightX"></mpath> </animateMOtion> </circle> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m300,150c-300,0 -300,0 -300,0" id="rightX" /> </svg> <!-- 上 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="top"> <rect class="rect "></rect> <circle x="0" y="0" r="5" stroke="none" fill="red"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#topY"></mpath> </animateMOtion> </circle> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m150.75,0.75l0,300" id="topY" /> </svg> <!-- 下 --> <svg xmlns="http://www.w3/org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bottom"> <rect class="rect "></rect> <circle x="0" y="0" r="5" stroke="none" fill="red"> <animateMOtion dur="3s" begin="infinite"> <mpath xlink:href="#bottomY"></mpath> </animateMOtion> </circle> <path fill="#fff" stroke="#000" stroke-width="1.5" stroke-opacity="null" fill-opacity="null" opacity="0.5" d="m150.75,0.75l0,300" id="bottomY" /> </svg> </div> </div>
路徑動畫是有animateMotion
元素作的因此能夠不是直線,只是爲了方便設計,我吧path
路徑設計成了直線
有興趣的能夠本身設計一下。
路徑是我用 Method Draw 畫的 editor.method.ac/
接下來就是重點的路徑控制了
$(document).ready(function () { const animate = document.getElementsByTagName('animateMotion'); // 0 frontY 1 frontX 2 behindY 3 behindX 4 leftX 5 rightX 6 topY 7 bottomY var frontY = animate[0], frontX = animate[1], behindY = animate[2], behindX = animate[3], leftX = animate[4], rightX = animate[5], topY = animate[6], bottomY = animate[7]; // Y面球體運動 (() => { //先執行一次 frontY.beginElement(); setTimeout(() => { bottomY.beginElement(); }, 3000); setTimeout(() => { behindY.beginElement(); }, 6000); setTimeout(() => { topY.beginElement(); }, 9000); // 循環執行動畫 var time = setInterval(() => { frontY.beginElement(); setTimeout(() => { bottomY.beginElement(); }, 3000); setTimeout(() => { behindY.beginElement(); }, 6000); setTimeout(() => { topY.beginElement(); }, 9000); }, 12000); })(); // X面球體運動 (() => { //先執行一次 frontX.beginElement(); setTimeout(() => { leftX.beginElement(); }, 3000); setTimeout(() => { behindX.beginElement(); }, 6000); setTimeout(() => { rightX.beginElement(); }, 9000); // 循環執行動畫 var time = setInterval(() => { frontX.beginElement(); setTimeout(() => { leftX.beginElement(); }, 3000); setTimeout(() => { behindX.beginElement(); }, 6000); setTimeout(() => { rightX.beginElement(); }, 9000); }, 12000); })(); })
我設置的是讓animateMotion元素的起始值begin
爲infinite
,在頁面加載完畢後動畫不會自動執行。
我用jQuery來控制動畫的執行順序。
首先獲取每一個動畫元素const animate = document.getElementsByTagName('animateMotion');
,以後將每一個動畫元素都標記好。
接着使用計時器setInterval
和setTimeout
計時器來控制動畫。首先使用setInterval
來控制動畫循環執行。接着在setInterval
中用setTimeout
設置動畫執行的順序,每一個setTimeout
計時器的延遲都爲以前全部動畫時間之和。模塊化的最好先設置一個動畫對象數組,而後將動畫順序加入數組。
最後附加兩個API
// svg指當前svg DOM元素 // 暫停 svg.pauseAnimations(); // 重啓動 svg.unpauseAnimations()
兩個API可已暫停當前動畫,關於詳情請看張鑫旭大佬的文章鑫空間
旋轉控制是我還沒完善的地方,用戶體驗不是十分好,還望大佬們幫我指出錯誤。另外一個旋轉方案過一兩天再添加上來。
代碼:
var X = 0;//記錄X軸旋轉過的角度 var Y = 0;//記錄Y軸旋轉過的角度 // 旋轉控制 $('.container').mousedown(function (event) { var mousedownX = event.clientX; var mousedownY = event.clientY; $('body').mousemove(function (event) { var mousemoveX = event.clientX; var mousemoveY = event.clientY; var scaleY = ((mousemoveX - mousedownX) / 200); var scaleX = ((mousemoveY - mousedownY) / 200); Y = ((Y + scaleY) % 360); X = ((X + scaleX) % 360); $('.container').animate({}, function () { $('.container').css({ 'transform': `rotateX(${X}deg) rotateY(${Y}deg)` }); }) }) }) $('body').mouseup(function () { $('body').unbind('mousemove'); $('body').unbind('mousedown'); })
首先設置兩個變量X,Y這是記錄這個立方體真正旋轉了多少角度。
而後在立方體.container
元素上添加鼠標點擊事件mousedown
事件,在回調函數中作處理內容。回調函數中先記錄下來鼠標點擊的位置。
接着在body
上添加鼠標移動mousemove
事件由於咱們移動不能只在立方體上,移動的範圍要擴大到頁面上。接着在移動事件中的回調函數作旋轉處理,首先記錄下來移動後鼠標的位置,計算出鼠標移動的距離而後除以一個數var scaleY = ((mousemoveX - mousedownX) / 200);
注意其中的200沒有真正表明的意義,只是由於鼠標移動的距離數值相對於旋轉的角度來講比較大,因此除以200減小它移動的角度,能夠隨意更改,其中鼠標在X軸上移動用戶須要的是圖形在以Y軸旋轉。接着我麼要計算立方體真正對於初始旋轉了多少角度咱們最好作一下範圍限制(取模運算),Y = ((Y + scaleY) % 360);
最後就是設置屬性了,先用$('.container').animate()
讓旋轉用動畫的形式來作成,而後設置旋轉角度$('.container').css({ 'transform':
rotateX(${X}deg) rotateY(${Y}deg) });
用css()
方法來設置旋轉角度。
最後將github庫放上來
github庫