我使用了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库连接放上来