- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个具有定义的宽度和高度的视口(viewport)。我克隆了右侧 View 之外的一个元素,然后随机将其飞过视口(viewport) 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
}
...
足够简单的动画。这是有趣的部分:在每一步中,我都想对这个元素应用一些物理原理。
类似这样的:
...
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
});
}
}
...
基本上发生的事情不是从右到左直线飞行,而是减速、加速、随机上升和下降,正如我的意图。
我面临的问题是,有时“风”足够强,以至于当步数达到计算的总步数时,元素在视口(viewport)上仍然可见,并且它会消失(这发生在我的complete:function(){ ...$(this).remove(); ...}
显然,JQuery 认为动画已经完成,因为它计算了步骤并说“我正在为这个对象设置动画,在这么多毫秒内经过这么多步骤 - 它就在那里”。但是风动画在动画队列之外,所以这个动画过程并不明智。
我想要的是开始动画并保持动画直到元素以任何方向退出视口(viewport) - 一旦它不再可见,无论是从其初始飞行路径还是从屏幕上吹来的风,我将检测到它并触发 onComplete
打回来。我唯一能想到的就是将此动画放在函数内并放在 complete:function(){}
中对自身进行递归调用,然后在 step:function(){}
内我会进行“在视口(viewport)中可见”检查并调用 stop(true,false)
如果true
。这似乎是一个非常昂贵的检查 - 在 400-1200 毫秒内运行该计算 100 多次可能会使动画不稳定,因此我正在寻找更优雅的解决方案。
TL;博士:由于设置了其他动画而尚未到达目的地,我如何保持动画效果?
更新:我申请了@mu is too short's idea并想出了这个:
/**
* 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));
}
这是我到目前为止所拥有的: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);
}
如果内部计算中有任何内容需要反复计算,请在 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);
如果您有很多动画对象,您可能希望在 animate_it
上执行“it is gone”回调,这样您就可以保持外部计时器列表干净且无瑕疵。
尝试使用 animate
执行此操作的问题是 animate
在开始时计算步骤数,然后您可以更改它。您需要的步骤数量不定,但 animate
并不关心(它甚至比蜜獾还关心)。
关于JQuery animate - 有什么方法可以完整触发 "stall"吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6969218/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!