Here's a working example of everything below.
我的做法是先简化html:
<div id="slide_nav">
<a href="#" class="prev">« Previous</a>
<a href="#" class="next">Next »</a>
</div>
<ul id="slide_container">
<li class="one slide">one</li>
<li class="two slide focused">two</li>
<li class="three slide">three</li>
</ul>
我没有使用所有固定宽度(例如width: 9999px;),而是将所有 li 属性设置为 100% 的宽度并使用绝对位置。然后你可以简单地改变left 属性来移动东西。
#slide_container li {
width: 100%;
height: 600px;
display: block;
position: absolute;
top: 0;
left: 0;
}
#slide_container .one {
background-color: #900;
left: -100%;
}
#slide_container .two {
display: block;
background-color: #090;
}
#slide_container .three {
background-color: #009;
left: 100%;
}
起初这可能看起来很棘手,因为animate 不太喜欢百分比。但是您的元素会自动填充它们的容器,因此值得在页面加载时进行额外的小转换以使其全部正常工作:
// change all percentages to pixels because animate hates percent
// and seems to lose position over time
var base = 0-$('#slide_container li').eq(0).outerWidth(true);
$('#slide_container li').each(function() {
var $this = $(this);
$this.css('left', base+'px');
base += $this.outerWidth(true);
});
然后创建一个插件,它会简化你的代码结构:
$.fn.extend({
slideMyDivs: function(method, amount) {
if (!amount) {
amount = this.eq(0).outerWidth(true);
}
switch (method) {
case 'prev':
this.stop(true, true).animate({
left: '+=' + amount
}, {
duration: 600,
easing: 'easeInOutExpo'
});
break;
case 'next':
this.stop(true, true).animate({
left: '-=' + amount
}, {
duration: 600,
easing: 'easeInOutExpo'
});
break;
default:
throw new Error('Invalid method: ' + method);
}
return this;
}
});
然后我会设置一个方法来在您到达列表的结尾/开始时禁用链接:
function toggleLinks() {
if (!hasPrev()) {
$('#slide_nav .prev')
.addClass('disabled')
.bind('click.disabled', function() { return false; });
}
else {
$('#slide_nav .prev').removeClass('disabled').unbind('.disabled');
}
if (!hasNext()) {
$('#slide_nav .next').addClass('disabled').bind('click.disabled', function() {
return false;
});
}
else {
$('#slide_nav .next').removeClass('disabled').unbind('.disabled');
}
}
或者,如果你想让它循环回来(这有点超出了这个问题的范围),你可以通过设置它的 left css 属性来将最后一个元素移动到开头,如下所示:
function send_to_start($elm) {
var newPos = $('#slide_container li').eq(0).pos().left - $elm.outerWidth(true);
$elm.css('left', newPos+'px');
}
然后我会像这样设置事件:
$('#slide_nav a').mouseenter(function() {
if ($(this).hasClass('disabled')) {
return false;
}
else {
var p = $(this).hasClass('prev') ? 'prev' : 'next';
showPreview(p);
}
}).mouseleave(function() {
cancelPreview($(this).hasClass('prev') ? 'prev' : 'next');
});
$('#slide_nav .prev').click(function() {
cancelPreview('prev');
if (hasPrev()) {
$('#slide_container li').slideMyDivs('prev').filter('.focused').removeClass('focused').prev().addClass('focused');
toggleLinks();
}
return false;
});
$('#slide_nav .next').click(function() {
cancelPreview('next');
if (hasNext()) {
$('#slide_container li').slideMyDivs('next').filter('.focused').removeClass('focused').next().addClass('focused');
toggleLinks();
}
return false;
});
以下是这些事件处理程序调用的杂项函数:
function showPreview(method) {
var p = method == 'prev',
$n = p ? $('#slide_container li.focused').prev() : $('#slide_container li.focused').next();
$n.addClass('previewActive')
.slideMyDivs((p ? 'prev' : 'next'), '75');
}
function cancelPreview(method) {
var p = method == 'prev';
$('#slide_container li.previewActive')
.removeClass('previewActive')
.slideMyDivs((p ? 'next' : 'prev'), '75');
}
function hasPrev() {
return $('#slide_container .focused').prev().length > 0;
}
function hasNext() {
return $('#slide_container .focused').next().length > 0;
}
function toggleLinks() {
if (!hasPrev()) {
$('#slide_nav .prev')
.addClass('disabled')
.bind('click.disabled', function() { return false; });
}
else {
$('#slide_nav .prev').removeClass('disabled').unbind('.disabled');
}
if (!hasNext()) {
$('#slide_nav .next').addClass('disabled').bind('click.disabled', function() {
return false;
});
}
else {
$('#slide_nav .next').removeClass('disabled').unbind('.disabled');
}
}