下面代码,点击一次向左,等完成后,再点击没问题,如果一直点,快速点,到头后还能跑过,这个怎么处理,是不是应该让点击执行完后才可再次点击,应该怎么写
http://jsfiddle.net/N72mP/1/
<div class="cover no-select">
<ul style="left:226px;" class="cover-imgs">
<li><img src="img.jpg" data-id="106851470"></li>
<li><img src="img.jpg" data-id="101810541"></li>
<li><img src="img.jpg" data-id="101810525"></li>
<li><img src="img.jpg" data-id="101810507"></li>
</ul>
<div class="left arrow none">
<div class="arrow-img"></div>
</div>
<div class="right arrow">
<div class="arrow-img"></div>
</div>
</div>
$(document).ready(function () {
var $Imgs=$('.no-select .cover-imgs'),
$ImgsLi=$Imgs.children('li'),
$ImgsLen=$ImgsLi.length,
$ImgsLeft=$('.no-select .left .arrow-img'),
$ImgsRight=$('.no-select .right .arrow-img');
$ImgsLeft.bind('mousedown',function(){
if( ($Imgs.position().left >= 0) ){
$(this).parent().addClass('none');
}
if( ($Imgs.position().left < 226) ){
var nowLeft = $Imgs.position().left+226;
$ImgsRight.parent().removeClass('none');
$Imgs.animate({'left':nowLeft},300);
}
});
$ImgsRight.bind('mousedown',function(){
if( ($Imgs.position().left <= 226) && ($Imgs.position().left >= (-($ImgsLen-3)*226)) ){
var nowLeft = $Imgs.position().left-226;
$ImgsLeft.parent().removeClass('none');
$Imgs.animate({'left':nowLeft},300);
}
if( $Imgs.position().left <= (-($ImgsLen-3)*226) ){
$(this).parent().addClass('none');
}
});
});
这问题我也碰到过,当时研究了github的一些轮播的源码。
终于找到了通用的解决办法啊。
同沙渺所说的算法。
可以参考本人写的一个图片轮播插件:https://github.com/xiaomingming/easySwitch/blob/master/js/easySwitch.js 中的scroll方法实现。
实际上,解决当前的动画累积问题,需要使用stop方法,而对于当前动画和其他动画的先后执行,则需要stop方法配合设置动画标志位来共同协调的。
因此楼上举例stop太过片面了。
<script>
$(".banpic li:first").clone(true).appendTo(".banpic")
$(".banpic li:last").prev("li").clone(true).prependTo(".banpic")
$(function () {
var container = $('.banner');
var list = $('.banpic');
var prev = $('.prev');
var next = $('.next');
var len = $(".banpic li").length-2;
var index = 1;
var interval = 5000;
var timer;
list.width(1000*(len+2));
function animate (offset) {
var left = parseInt(list.css('left')) + offset;
if (offset>0) {
offset = '+=' + offset;
}
else {
offset = '-=' + Math.abs(offset);
}
list.animate({'left': offset}, 1000, function () {
if(left > -200){
list.css('left', -1000 * len);
}
if(left < (-1000 * len)) {
list.css('left', -1000);
}
});
}
function play() {
timer = setTimeout(function () {
next.trigger('click');
play();
}, interval);
}
function stop() {
clearTimeout(timer);
}
next.bind('click', function () {
if (list.is(':animated')) {
return;
}
if (index == len) {
index = 1;
}
else {
index += 1;
}
animate(-1000);
});
prev.bind('click', function () {
if (list.is(':animated')) {
return;
}
if (index == 1) {
index = len;
}
else {
index -= 1;
}
animate(1000);
});
container.hover(stop, play);
play();
});
</script>
有jsfiddle就很容易调了。
第一想法当然是“让mousedown
事件在执行完毕之前不能重复触发”。但千万小心——这个显然的思路完全不对:因为jQuery的动画过程是异步的!无论动画多长,这个mousedown
事件都会立刻执行完毕。控制这个事件的重复触发必然是错误的。
正确的方法是:让动画效果的播放过程中,不再触发mousedown
事件。
我用了个简单的方法:
- 并不刻意反复的启用/禁止事件响应。
- 动画开始前,设定容器元素的一个标志。
- 使用
.animate()
的回调函数,控制动画结束后把标志去掉。 - 如果
mousedown
事件执行时看到了标志,则直接跳出,不做实际动作。
http://jsfiddle.net/N72mP/5/
标志数据打在容器父元素上(而不是打在this
上)的意义,是因为动画效果是针对容器而言唯一,而不是针对按钮而言。这样做可以防止先按【右】,赶在动画结束前再迅速按【左】引发的bug。
加个计数器,默认为0,然后在绑定的事件里加判断。
为0时,不执行左翻,为N(tab个数)-1时不执行右翻。
或用第三方库,省去自己写了,站在巨人肩上,这就是开源的意义所在。
我用阿里系的:http://aralejs.org/switchable/examples/carousel.html
用过Requirejs之类的模块加载器会很容易上手,没用过看一遍文档也基本会了。
题主把一个简单的幻灯片弄得太复杂了
var $ImgsLeft=$('.no-select .left .arrow-img')
var n=$('li img').size();
$ImgsLeft.click(function(){
if(n>=0)
{
$('ul').stop(true,true).animate({left:'-=46px'});
n--
}
})