我使用了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
代碼:bash
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//放置六個svg平面旋轉平移後,可視做爲立方體
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)
複製代碼
一般有兩種方式作成立方體。svg
.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
元素來作的。
首先每一個svg
中圓點的路徑是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);
})();
})
複製代碼
個人控制方式是所有由jQuery來控制,在animateMotion
元素中設置的起始時間begin
屬性爲infinite
這是在頁面接在完後不會本身執行的。
我使用jQuery來控制動畫的開始。
首先 先獲取每一個動畫元素 const animate = document.getElementsByTagName('animateMotion');
將每一個動畫元素都標記好是什麼動畫。
接着 我在這使用了計時器setInterval
和setTimeout
來控制動畫。 用setInterval
來循環播放動畫,再每次循環中分別用setTimeout
來控制動畫的的前後順序。 每一個setTimeout
計時器的延遲等於以前全部動畫的總時間,能夠獲取元素的dur等方法獲取和設置,在這爲圖方便設置了固定值。有興趣的能夠設置一個動畫數組,裏面按序添加animateMotion
動畫元素。每一個setTimeout
計時器的延時設置爲以前動畫的時間之和便可。
最後有兩個方法能夠控制動畫的中止與繼續,是svg
內置的API
若是要使用這兩個API的話,最好將動畫的begin
值設置爲上一個動畫.end
,begin
的值支持不少類型,詳情請看張鑫旭大佬的文章
www.zhangxinxu.com/wordpress/2…
// svg指當前svg DOM元素
// 暫停
svg.pauseAnimations();
// 重啓動
svg.unpauseAnimations()
複製代碼
旋轉控制是我還沒完善的地方,體驗不是十分好,還望大佬們幫我指出錯誤。另外一個旋轉方案過一兩天再添加上來
先上代碼:
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
的變量。
接着在立方體元素中添加mousedown()
事件,在mousedown的回調函數中先記錄下鼠標點擊的位置 var mousemoveX = event.clientX;
而且在body
元素上添加mousemove()
事件由於是要在整個頁面上移動。
最後就是最重要的移動部分,先記錄鼠標移動的位置 var mousemoveX = event.clientX;
而後計算鼠標移動的距離var scaleY = ((mousemoveX - mousedownX) / 200);
這裏面200是可隨意更改的,由於鼠標移動距離對於旋轉角度來講太大了因此要除以一個倍率能夠本身來設置,其次是計算正方體對於初始的位置旋轉的多少角度 Y = ((Y + scaleY) % 360);
這裏要除以360作範圍限制,其實不添加也能夠,rotate
屬性支持超過360度。接着就是設置旋轉角度了
$('.container').animate({}, function () {
$('.container').css({ 'transform': `rotateX(${X}deg) rotateY(${Y}deg)` });
})
複製代碼
經過animate()
方法來將旋轉作動畫效果在裏邊經過css()
方法來設置旋轉的角度。
第二種方案: 第二種方案是不須要用戶點擊,實時監聽鼠標移動,鼠標移動就會旋轉。我將旋轉方向判斷的基點設置爲屏幕的中點。 上代碼
var HalfX=window.innerWidth;
var HalfY=window.innerHeight;
var mousemoveX = null;
var mousemoveY = null;
window.addEventListener('resize',onchange);
function onchange(){
var HalfX=window.innerWidth;
var HalfY=window.innerHeight;
}
$('body').mousemove((event)=>{
mousemoveX = ((event.clientX - HalfX))%360;
mousemoveY = ((event.clientY - HalfY))%360;
$('.container').animate({},function(){
$('.container').css('transform',`rotateX(${mousemoveY}deg)rotateY(${mousemoveX}deg)`);
})
})
複製代碼
方案的更改沒有太大的差異。只是觸發的事件不一樣和鼠標移動距離計算的基點不一樣。 在第二個方案中咱們不須要儲存上一次的旋轉的角度。由於咱們相對的基點是絕對的,角度的更改不會有相對座標系的問題,每個位置相對於立方體旋轉的角度是固定的,不過咱們也須要記錄下來基點的值,當屏幕改變時咱們的基點也須要改變onchange()
方法。
最後將github庫連接放上來