我试图实现的效果是点击一个按钮,一个由8个三角形组成的圆圈旋转。当它停止时,选择圆顶顶部的三角形。然后打开相对于所选片段的fancybox叠加(这最后一部分还没有工作)。选择片段的顺序对于用户来说是随机的,但是它可以预设为我在CSS中完成的(当前:第3>第6>第1>第8>第2>第5>第7>第4次)。
我已经创建了一个codepen来显示我目前的进展,你可以通过访问下面的链接来看到它很难解释。
http://codepen.io/moy/pen/DrbAL
点击' Spin'按钮圆圈旋转3次(1080度)+另外270度,所以第3个列表项位于div的顶部 - 这很好。
我的第一个问题是:在第二次点击按钮时,圆圈需要再次旋转3次,然后再多一点,将下一个选定的列表项/段(6)定位在div的顶部,这样每个剩余的项目。有没有办法做到这一点,而不必添加1080到圆已经旋转的数量?因此,值始终为1080deg
+圆圈需要旋转以将相关细分位于div顶部的额外金额。否则,最后一项的值将达到10000度!如果必须这样做,我想我将不得不忍受它并戴上数学帽。
第二个问题是:圆圈完成旋转后,如何显示相关的花式框叠加? ID目前是每个叠加的标题,但可以很容易地覆盖-1,叠加-2等,以匹配每次旋转后在旋转轮上设置的spin-1,spin-2的类别。
谢谢,希望有人可以提供帮助!
答案 0 :(得分:6)
我发现这个问题非常有趣,因为我不久前在一个类似的项目上工作,所以这是我的意见。首先,我建议您使用Julian Shapiro的velocity插件制作动画,这将为您提供以下一些优势:
通过速度,旋转你的车轮可以简单地完成:
$(".wheel").velocity({
rotateZ : "-" + {degree} + "deg" // "-" minus to spin counterclockwise, remove otherwise
});
velocity 插件有一整套API选项,您可以浏览here。当然,您需要一种算法来计算每degree
个click
变量的新值。
现在,如果我理解正确,你有两个问题:
我将开始使用以下算法回答第二个问题:
_target = (_deg - (360 * parseInt(_deg / 360))) / 45;
其中_target
是所选片段的javascript index
,_deg
我们将轮子从前一个位置旋转到当前位置的度数。
工作原理:
按照上面的示例,您的车轮的初始状态是1号段(商业意识),从那里您需要移动到3号(团队工作),这意味着旋转车轮3次(1080度) )+另外两个45度的段(90度)= 1170 degrees
旋转。
所以,将该值应用于算法:
_target = (1170 - (360 * parseInt(1170 / 360))) / 45;
_target = (1170 - (360 * parseInt(3.25))) / 45;
_target = (1170 - (360 * 3)) / 45;
_target = (1170 - (1080)) / 45;
_target = (90) / 45;
_target = 2;
如果您认为在javascript中,组的第一个元素为index=0
,则第二个元素为index=1
,第三个元素为index=2
,等等。_target = 2
实际指向第三部分(团队工作)。无论你旋转了多少度,这个算法都能正常工作。
然后解雇fancybox很简单:
$(".fancybox").eq(_target).trigger("click");
上面的代码假设您已在脚本中的某处初始化了fancybox,如
$(".fancybox").fancybox({ // API options });
现在,对于第一个问题,我看到3种可能的算法,您可以在分离的函数中设置,以便在按钮click
之后调用:
返回图案化的顺序(每个click
前进3个段),如1,4,7,2,5,8,3,6 ...然后循环。每个段在循环之前至少显示一次:
function ordSequential() {
// order : 1,4,7,2,5,8,3,6 ... then loops
return _deg = _deg + (45*3) + 1080;
};
它假设初始值为_deg = 0
。请注意,您始终可以更改因子3
以更改模式。
因此,我们可以使用 velocity 来使用度量来旋转:
1
0.4
完整代码
// sequential order
// advances 3 segments each click
var _target, _deg = 0;
function ordSequential() {
// order : 1,4,7,2,5,8,3,6 ... then loops
return _deg = _deg + (45*3) + 1080;
};
jQuery(document).ready(function ($) {
$(".skills-wheel .btn").on("click", function (e) {
// select algorithm sequential, random or preset :
ordSequential();
_target = (_deg - (360 * parseInt(_deg / 360))) / 45;
// start animation
// reset opacity of all segments to 1
$(".fancybox").parent("li").velocity({
opacity: 1
}, {
duration: 100,
complete: function () {
$(".wheel").velocity({
rotateZ: "-" + _deg + "deg"
}, {
duration: 3000,
complete: function (elements) {
// after spinning animation is completed, set opacity of target segment's parent
$(".fancybox").parent("li").eq(_target).velocity({
opacity: 0.4
}, {
duration: 100,
// after opacity is completed, fire targeted segment in fancybox
complete: function () {
$(".fancybox").eq(_target).trigger("click");
} // third animation completed
}); // nested velocity 2
} // second animation completed
}); // nested velocity 1
} // first animation completed
}); // velocity
return false;
}); // click
// initialize fancybox
$(".fancybox").fancybox({
maxWidth: "85%"
});
}); // ready
参见 JSFIDDLE
注意在complete
回调中使用嵌套*力度函数
*编辑:如果您使用的是Velocity的UI包,则可以使用函数
.RunSequence()
使嵌套动画序列更易于管理。使用此方法查看更新的 JSFIDDLE 。确保使用最新版本的Velocity.js和UI包(v1.1.0,如今[2014年10月8日])http://cdnjs.com/libraries/velocity
返回上面示例中的预设顺序
3rd > 6th > 1st > 8th > 2nd > 5th > 7th > 4th
代码基本相同,但算法稍微复杂一些。首先,我们需要在数组中预设顺序以及其他支持变量:
var presetPos = [3, 6, 1, 8, 2, 5, 7, 4],
presetInit = true,
spin_count = 0;
注意 presetPos
数组包含实际的段号,而不是javascript index
。另请注意使用标志presetInit
,它告诉车轮是否处于初始状态(我们在第一次旋转后将其切换到false
)
预设算法的调味品是计算数组中current
和next
段之间的差异(以度为单位),以便我们知道多少度车轮需要旋转:
function ordPreset() {
// initial state?
if (presetInit) {
presetInit = false;
return _deg = _deg + ((presetPos[spin_count] - 1) * 45) + 1080;
} else {
var _current = presetPos[spin_count];
var _next = presetPos[spin_count > 6 ? 0 : spin_count + 1];
var _diff = _next - _current;
spin_count = spin_count > 6 ? 0 : ++spin_count;
return _deg = _deg + (_diff * 45) + 1080;
};
};
参见 JSFIDDLE
返回0-7范围内的随机顺序。
随机算法非常简单。请参阅this以供参考。
function ordRandom() {
return _deg = _deg + ((Math.floor(Math.random() * (8 - 1 + 1)) + 0) * 45) + 1080;
};
然而click
方法中的逻辑有点复杂。在您理想的世界中,所选片段应该是完全随机的,但从不选择之前使用过的片段。一旦选择了所有8
结束(按钮将停止转动轮子)。
需要考虑几个因素:首先,我们需要一个数组来说明从未使用过的段。
var _index = [0,1,2,3,4,5,6,7];
注意此数组与每个细分的index
有关。
此外,我们需要一个标志,让我们通过随机选择循环(使用while
),直到我们找到一个从未使用过的index
。
var _repeatRandom = true;
然后,使用index
方法从阵列中删除随机选择的.splice()
非常重要,以确保我们不会再次使用它。
点击事件的代码:
$(".skills-wheel .btn").on("click", function (e) {
// select algorithm sequential, random or preset :
// if random order, don't repeat the same
_repeatRandom = _index.length == 0 ? false : true;
// loop until find one that has never been used
while (_repeatRandom) {
ordRandom();
_target = (_deg - (360 * parseInt(_deg / 360))) / 45;
var _inArray = $.inArray(_target, _index);
if (_inArray > -1) {
// target is in the array
_repeatRandom = false; // break while loop
_index.splice(_inArray, 1); // remove segment from array so it won't be repeated
// start animation
// reset opacity of all segments to 1
$(".fancybox").parent("li").velocity({
opacity : 1
}, {
duration : 100,
complete : function () {
$(".wheel").velocity({
rotateZ : "-" + _deg + "deg"
}, {
// addtional settings and callback
duration : 3000,
complete : function (elements) {
// after spinning animation is completed, set opacity of target segment's parent
$(".fancybox").parent("li").eq(_target).velocity({
opacity : 0.4
}, {
duration : 100,
// after opacity is completed, fire targeted segment in fancybox
complete : function () {
$(".fancybox").eq(_target).trigger("click");
} // third animation completed
}); // nested velocity 2
} // second animation completed
}); // nested velocity 1
} // first animation completed
}); // velocity
}; // if
}; // while
return false;
}); // click
参见 JSFIDDLE
最后一点:
transform
效果(.wheel.spin-1
,.wheel.spin-2
,.wheel.spin-3
等。)duration
等),您可能需要根据自己的喜好和需求进行调整。