我正在继续previous post,但我想我会打开一个新线程,因为它采用了不同的方法并且有更多的实际代码。无论如何,我试图得到一个无限循环,div通过窗口滚动(另一个帖子有一个图像,下面的代码可以工作)。
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Bleh...</title>
<style type="text/css" media="screen">
body {
padding: 0;
text-align: center;
}
#container {
width: 1000px;
padding: 10px;
border: 1px solid #bfbfbf;
margin: 0 auto;
position: relative;
}
#window {
width: 400px;
height: 100px;
padding: 10px;
border: 3px solid #666;
margin: 0 auto;
}
.box {
height: 100px;
width: 100px;
border: 1px solid #666666;
position: absolute;
z-index: -1;
}
.red { background-color: #ff6868;}
.green { background-color: 7cd980;}
.blue { background-color: #5793ea;}
.yellow { background-color: #f9f69e;}
.purple { background-color: #ffbffc;}
.cyan { background-color: #bff3ff;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
$(window).load(function() {
arrangeBoxes();
setInterval('shiftLeft()', 3000);
});
// arrange the boxes to be aligned in a row
function arrangeBoxes() {
$('.box').each( function(i, item) {
var position = $('#window').position().left + 3 + i * ( $(item).width() + 10 );
$(item).css('left', position+'px')
});
}
// shifts all the boxes to the left, then checks if any left the window
function shiftLeft() {
$('.box').animate({'left' : "-=100px"}, 3000, 'linear');
checkEdge();
}
// returns the new location for the box that exited the window
function getNewPosition() {
return $('.box:last').position().left + $('.box:last').outerWidth() + 10;
}
// if the box is outside the window, move it to the end
function checkEdge() {
var windowsLeftEdge = $('#window').position().left;
$('.box').each( function(i, box) {
// right edge of the sliding box
var boxRightEdge = $(box).position().left + $(box).width();
// position of last box + width + 10px
var newPosition = getNewPosition();
if ( $(box).attr('class').indexOf('red') >=0 ) {
console.log('box edge: ' + boxRightEdge + ' window edge: ' + windowsLeftEdge + ' new pos: ' +newPosition);
}
if ( parseFloat(boxRightEdge) < parseFloat(windowsLeftEdge) ) {
$(box).css('left', newPosition);
$(box).remove().appendTo('#window');
first = $('.box:first').attr('class');
console.log('first is ' + first);
}
});
}
</script>
</head>
<body id="index">
<div id="container">
<div id="window">
<div class="box red"></div>
<div class="box green"></div>
<div class="box blue"></div>
<div class="box yellow"></div>
<div class="box purple"></div>
<div class="box cyan"></div>
</div>
</div>
</body>
</html>
无论如何,问题是我可以让盒子向左移动,但是当我运行整个东西时,我无法让前导框弹回到行尾。当我单独运行每个功能时(使用firebug) -
>> $('.box').animate({'left' : "-=100px"}, 3000, 'linear');
>> checkEdge()
效果很好。当我把它们组合在一起时,我只是从左到右连续运动,直到盒子离开屏幕,因此它们必须是它们如何相互作用。我希望这是有道理的(如果没有,将上面的代码块保存为html文件并在浏览器中运行)。我已经坚持了一段时间,所以任何帮助都会很棒。感谢。
答案 0 :(得分:4)
您需要像这样设置回调
$('.box').animate({'left' : "-=100px"}, 3000, 'linear', checkEdge());
checkEdge()
不是checkEdge
点击此处查看有效的解决方案http://jsbin.com/uceqi(只需复制粘贴代码)
如果你把牙箍放开,它实际上会有所不同。带有大括号的版本每个动画执行checkEdge()
一次(说实话,它实际上在动画开始之前执行checkEdge
。checkEdge()
函数在{甚至在$...animte(..)
本身执行之前就已达到{1}}语句。animate()
会导致函数作为参数传入,通常是正确的方法。
对于与选择器匹配的元素数,没有大括号的版本执行checkEdge
一次。在这种情况下6次。
从技术上讲,你的方法是正确的,因为它会在每个动画元素和 AFTER 动画时触发一次回调。
但是执行checkEdge
一旦这显然不是作者的意图(检查checkEdge
中的div循环)。当你在所有div上循环几次时,也会造成严重的滞后
6divs动画checkEdge
6x回调在所有div上->
回调循环->
36x执行==>
中的匿名函数!!
所以实际问题是回调被同时触发了6次并且全部被触发。因此,我们有一个竞争条件和动画混乱。由于多个checkEdge()
调用同时用于重新定位div。
但是你只注意到这一点,因为checkEdge()
和animation-speed
(shiftLeft)中的间隔是相同的。它们会不同((间隔+ ~1000ms)>动画速度)然后它也能正常工作。但当然动画不会流畅。动画停止后,setInterval
将触发1秒。
您可以查看此示例http://jsbin.com/iwapi3,其中说明了使用不带大括号的版本时会发生什么。等待一段时间,shitfLeft()
呼叫的计数器每3秒增加7。您还会注意到,在某些情况下,动画部分工作,一些div被移回列表的末尾(有时)。
一段时间后,点击按钮,观看带有大括号的版本如何在几次运行后对混乱进行排序(但现在正确的颜色顺序当中搞砸了)。并且每个动画只调用一次checkEdge()
。 (按下按钮后不久,你会得到另一个+7,因为一些回调仍在管道中)
答案 1 :(得分:0)
JavaScript执行不会等到你的动画函数花费3000毫秒。它启动动画功能,但然后(在0-1毫秒后)移动到你的checkEdge()函数。您不需要检查checkEdge()中的状态。
为了防止这种情况,您应该将checkEdge()函数作为回调函数添加到animate函数中,该函数将在3000ms之后执行。
试试这个:
$('.box').animate({'left' : "-=100px"}, 3000, 'linear', checkEdge);