Ali*_*guy 5 jquery jquery-animate
想象一下,我有一个具有定义宽度和高度的视口.我在右侧克隆一个元素,然后在一个随机y位置将它飞过视口,代码如下:
...
.css({
'left': BASE_NODE_INIT_LEFT_PX,
'top' : rand(BASE_NODE_INIT_TOP_MIN_PX, BASE_NODE_INIT_TOP_MAX_PX) + 'px',
'width': _width + 'px',
'height': _height + 'px',
})
.animate({
left: BASE_NODE_ANIMATE_DISTANCE_X_PX
}
...
Run Code Online (Sandbox Code Playgroud)
足够简单的动画.这是有趣的部分:在每一步我想对这个元素应用一些物理.
像这样的东西:
...
step:function(currentStep){
if($(this).data('animating-wind') !== true)
{
$(this).data('animating-wind',true);
var wind = (rand(1,2) == 2) ? '+=' + rand(1, 100) + 'px' : '-=' + rand(1, 100) + 'px';
$(this).animate({
'top': wind,
'text-indent': wind,
},{
duration: 500,
complete: function(){
$(this).data('animating-wind',false);
},
queue: false
});
}
}
...
Run Code Online (Sandbox Code Playgroud)
基本上发生的事情不是从右到左直线飞行,而是随着我的意图减速,加速,随机升起和下降.
我面临的问题是,有时"风"足够强,以便当步数达到总计算步数时,元素在视口中仍然可见,并且它将消失(这发生在我的身上) complete:function(){ ...$(this).remove(); ...}
显然正在发生的事情是JQuery认为动画是完整的,因为它计算了这些步骤,并且说"我在这很多步骤中通过这么多毫秒的时间动画这个对象很多像素 - 就在那里".但是风动画是在动画队列之外,所以这个动画过程是非常明智的.
我想要的是开始动画并保持动画直到元素从任何方向退出视口 - 一旦它不再可见,无论是从其初始飞行路径还是从风吹出屏幕,我都会检测到它并触发onComplete回调.我唯一能想到的就是将这个动画放在一个函数中complete:function(){},然后对它自己做一个递归调用,然后在里面step:function(){}我做"视口中的可见"检查并调用stop(true,false)if true.这似乎是一个非常昂贵的检查 - 在400-1200ms运行计算100次以上可能会使动画波动,所以我正在寻找更优雅的解决方案.
TL; DR: 如果由于其上设置了额外的动画,如果它尚未到达目的地,我如何保持动画效果?
更新:我应用@mu是太短暂的想法,并想出了这个:
/**
* Create a new clone of the master div for user interaction. Position it
* randomly off the canvas, and animate it across at a random speed.
*/
function spawn_target() {
spawn_timeout = setTimeout(function() {
var bonus = (rand(1, BONUS_ODDS) == BONUS_ODDS) ? ' ' + BONUS_CLASS : '';
var _img_src = (bonus.length > 0) ? BONUS_NODE_IMG_SRC : BASE_NODE_IMG_SRC;
var _width = $('#' + BASE_NODE_ID).width();
_width = Math.floor(rand(_width / 3, _width));
var _height = _width;
var _framerate = 10 - Math.floor(_height/10);
var _clone = $('#' + BASE_NODE_ID).clone().addClass(CLONE_CLASS + bonus).attr('id', CLONE_ID).appendTo('#' + CANVAS_ID).css({
'left': BASE_NODE_INIT_LEFT_PX,
'top': rand(BASE_NODE_INIT_TOP_MIN_PX, BASE_NODE_INIT_TOP_MAX_PX) + 'px',
'width': _width + 'px',
'height': _height + 'px',
})
$(_clone).children('img').attr('src', _img_src);
/**
* Handle the actual flight across the viewport
* @param object _this The clone we are animating manually
* @return object pointer This contains the interval so we can clear it later
*/
function fly(_this) {
var animating_wind = false;
var pointer = {
timer_id: null
};
pointer.timer_id = setInterval(function() {
// Get rid of the node if it is no longer visible in the viewport
if (!$(_this).is(':onviewport')) {
clearInterval(pointer.timer_id);
$(_this).remove();
adj_game_data(GAME_DATA_LIVES_ID, -1);
check_lives();
spawn_target();
}
// Move node along with slight realism
var distance = rand(FLY_DISTANCE_MIN, FLY_DISTANCE_MAX);
$(_this).css('left', '-=' + distance + 'px');
// Only trigger the wind animation when it is idle
if (animating_wind !== true) {
animating_wind = true;
// Setup the wind physics
var _wind_power = rand(WIND_POWER_MIN, WIND_POWER_MAX);
var _wind_dir = (rand(1, 2) == 2) ? '+=' : '-=';
// Override wind direction to keep node inside viewport
if(($(_this).offset().top + $(_this).height() + _wind_power) > CANVAS_HEIGHT)
{
_wind_dir = '-=';
}
if(($(_this).offset().top - _wind_power) < CANVAS_TOP_BUFFER_PX)
{
_wind_dir = '+=';
}
var _wind = _wind_dir + _wind_power + 'px';
// Apply the wind physics and don't let the node break the top or bottom
// boundaries of the viewport
$(_this).animate({
'top': _wind
}, {
duration: WIND_ANIMATION_DURATION,
complete: function() {
animating_wind = false;
},
queue: false
});
}
}, _framerate);
return pointer;
}
$(_clone).data('interval', fly(_clone));
}, rand(SPAWN_TARGET_TIMEOUT_MIN, SPAWN_TARGET_TIMEOUT_MAX));
}
Run Code Online (Sandbox Code Playgroud)
这是我到目前为止所拥有的:http://jsfiddle.net/AlienWebguy/DmtQ7/embedded/result/
我喜欢这个想法虽然看起来JQuery应该有内置的东西,这是我所希望的.现在,而不是$(obj).stop()我必须clearInterval($(obj).data('interval').timer_id);.*划伤头...
这就是我认为你应该做的(伪 JavaScript):
function animate_it($thing) {
var wind = false;
var timer_id = setInterval(function() {
// Compute the movement for this step.
// Then factor in the wind effect and update the `wind` variable.
// Then apply the movement to `$thing`.
if(it_is_off_the_page($thing))
clearInterval(timer_id);
}, n);
}
Run Code Online (Sandbox Code Playgroud)
如果内部计算中有任何东西需要反复计算,请在该animate_it级别预先计算它,并让闭包关闭它。您可能会想要尝试一下它,以弄清楚n应该是什么。
只需手动制作动画,这样您就不会与 jQuery 的animate功能发生冲突,并在知道动画完成时停止动画。这还允许您几乎免费地包含风的方向和强度(以便您的动画对象可以向后移动)。
您可能想要回到timer_id外部世界,以便可以从外部阻止整个事情。在这种情况下,您需要用一个元素对象来伪造一个指针:
function animate_it($thing) {
var wind = false;
var pointer = { timer_id: null };
pointer.timer_id = setInterval(function() {
// Compute the movement for this step.
// Then factor in the wind effect and update the `wind` variable.
// Then apply the movement to `$thing`.
if(it_is_off_the_page($thing)) {
clearInterval(pointer.timer_id);
pointer.timer_id = null;
}
}, n);
return pointer;
}
var timer = animate_it($thing);
// And then later, to shut it down...
if(timer.timer_id)
clearInterval(timer.timer_id);
Run Code Online (Sandbox Code Playgroud)
animate_it如果您有很多动画对象,您可能需要一个“它消失了”的回调,这样您就可以保持外部计时器列表干净且无残留。
尝试执行此操作的问题animate是animate在开始时计算步骤数,然后您可以更改它。您需要不同数量的步骤,但animate并不关心(它甚至不关心蜜獾)。
| 归档时间: |
|
| 查看次数: |
799 次 |
| 最近记录: |