Hãy tưởng tượng tôi có một chế độ xem có chiều rộng và chiều cao được xác định. Tôi clone một yếu tố ngoài tầm nhìn về phía bên phải, và bay nó qua cửa sổ xem mỗi vị trí ngẫu nhiên y
với mã như thế này:JQuery animate - bất kỳ cách nào để "stall" kích hoạt hoàn thành?
...
.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
}
...
Simple đủ hình ảnh động. Đây là phần thú vị: trên mỗi bước tôi muốn áp dụng một số vật lý cho yếu tố này.
Something như thế này:
...
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
});
}
}
...
Về cơ bản những gì xảy ra là thay vì bay thẳng qua từ phải sang trái, nó chậm lại, tăng tốc, và đặt ra và dips một cách ngẫu nhiên, cũng giống như tôi đang có ý định.
Sự cố tôi gặp phải là đôi khi "gió" đủ mạnh để phần tử vẫn hiển thị trên chế độ xem khi số bước đã đạt đến tổng số bước được tính toán và nó sẽ biến mất (điều này xảy ra Rõ ràng những gì đang xảy ra là JQuery nghĩ rằng hình ảnh động hoàn tất bởi vì nó tính toán các bước và nói "Tôi đang làm động vật này đối tượng này nhiều điểm ảnh trong nhiều mili giây này qua nhiều bước này - nó ở đó". hình động gió là bên ngoài hàng đợi hoạt ảnh vì vậy quá trình hoạt ảnh này không có gì là khôn ngoan.
Điều tôi muốn là bắt đầu hoạt ảnh và chỉ tiếp tục hoạt ảnh cho đến khi phần tử đã thoát khỏi chế độ xem theo bất kỳ hướng nào - một khi nó không còn nhìn thấy được nữa, hoặc từ đường bay ban đầu hoặc từ gió thổi tắt màn hình, tôi sẽ phát hiện và kích hoạt cuộc gọi lại onComplete
. Điều duy nhất tôi có thể nghĩ đến là đặt hoạt ảnh này bên trong một hàm và trong complete:function(){}
thực hiện cuộc gọi đệ quy cho chính nó, sau đó bên trong step:function(){}
Tôi sẽ thực hiện kiểm tra "hiển thị trong chế độ xem" và gọi stop(true,false)
nếu true
. Điều này có vẻ giống như một kiểm tra rất tốn kém - chạy mà tính toán 100 lần trong 400-1200ms có thể làm cho hoạt hình choppy vì vậy tôi đang tìm kiếm một giải pháp thanh lịch hơn.
TL; DR: Làm cách nào để tiếp tục tạo hoạt ảnh miễn là chưa đạt đến đích do hoạt ảnh bổ sung được đặt trên đó?
UPDATE: tôi áp dụng @mu is too short's idea và đến với điều này:
/**
* 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));
}
Dưới đây là những gì tôi có cho đến nay: http://jsfiddle.net/AlienWebguy/DmtQ7/embedded/result/
Tôi thích ý tưởng này mặc dù nó có vẻ như JQuery nên có một cái gì đó built- trong, đó là những gì tôi đã hy vọng. Bây giờ, thay vì $(obj).stop()
Tôi phải clearInterval($(obj).data('interval').timer_id);
. * Trầy xước đầu ...
Bạn đã cân nhắc thực hiện hoạt ảnh bằng tay chưa? Bạn có thể thực hiện một bước và gọi 'setTimeout' cho bước tiếp theo nếu bạn vẫn ở trên trang, sau đó tiếp tục lặp lại cho đến khi nó dừng lại. Sau đó, bạn sẽ không phải lo lắng về 'animate' cố gắng tính toán trước số bước. –
bạn có thể thử sử dụng + = thay vì - = để nó chảy "bằng gió". Điều này có nghĩa là nó sẽ vượt qua vị trí dừng thay vì undershoot, nhưng không có bản demo, tôi không biết tác dụng này sẽ dẫn đến kết quả gì. Bạn có thể đăng toàn bộ chức năng animate không? –
không thể đợi để xem bản trình diễn! –