我正在继续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文件并在浏览器中运行)。我已经坚持了一段时间,所以任何帮助都会很棒。谢谢。
最佳答案
您需要像这样设置回调
$('.box').animate({'left' : "-=100px"}, 3000, 'linear', checkEdge());
checkEdge()
不是checkEdge
在此处查看有效的解决方案http://jsbin.com/uceqi(只需复制粘贴您的代码)
在这里,如果不放置牙套,实际上会有所不同。带花括号的版本每个动画执行一次
checkEdge()
(实际上,实际上,它在动画开始之前执行checkEdge
。当checkEdge()
语句到达之前甚至在$...animte(..)
本身执行之前,就会调用animate()
函数。 checkEdge
将导致函数作为参数传递,通常是正确的方法。不带括号的版本将对与选择器匹配的元素数量执行一次
checkEdge
。在这种情况下6次。因此,从技术上来讲,您的方法是正确的,因为它将为每个动画元素触发一次回调,并在动画之后触发回调。
但是一旦执行
checkEdge
显然不是作者想要的(检查checkEdge
中的div循环)。当您在所有div上循环几次时,还会导致严重的滞后6div动画
->
6个回调触发的->
回调遍历所有div ==>
36个checkEdge()
中的匿名函数执行!因此,实际的问题是回调同时触发了6次。这样我们就有了比赛条件,动画变得混乱了。由于几个
checkEdge()
调用在重新定位div时同时工作。但是您仅会注意到这一点,因为
animation-speed
和setInterval
中的间隔(shiftLeft)是相同的。如果它们不同((间隔+〜1000ms)>动画速度),那么它也将正常工作。但是当然,动画不会流畅。因为shitfLeft()
在动画停止后会触发1秒。您可以检查此示例http://jsbin.com/iwapi3,该示例说明了使用不带花括号的版本时发生的情况。等待一段时间,
checkEdge()
调用的计数器每3秒增加7。您还将注意到,在某些情况下,动画会部分起作用,并且某些div有时会移回到列表的末尾。一段时间后,单击按钮,观察带有大括号的版本在运行几次后如何将混乱分类(但现在当然已经弄乱了正确的颜色顺序)。每个动画只调用一次
checkEdge()
。 (点击按钮后不久,您将获得+7的收益,因为某些回调仍在管道中)