我想询问是否有办法停止自动循环。我的目标是让暂停作为默认状态,当用户将鼠标悬停在我的循环(图像)上时,它会开始循环。
我设法扭转了悬停效果(mousenter启动循环,mouseleave暂停循环),这没问题。但我无法想象如何在我的页面加载时暂停循环。
HTML:
<div data-looper="go" class="looper">
<div class="looper-inner">
<div class="item">
<img src="http://lorempixel.com/320/240/sports" alt="">
</div>
<div class="item">
<img src="http://lorempixel.com/320/240/animals" alt="">
</div>
<div class="item">
<img src="http://lorempixel.com/320/240/food" alt="">
</div>
</div>
</div>
looper.js
;(function($, window, document, undefined) {
"use strict";
// css transition support detection
var cssTransitionSupport = (function(){
// body element
var body = document.body || document.documentElement,
// transition events with names
transEndEvents = {
'transition' : 'transitionend',
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'MsTransition' : 'MSTransitionEnd',
'OTransition' : 'oTransitionEnd otransitionend'
}, name;
// check for each transition type
for (name in transEndEvents){
// if transition type is supported
if (body.style[name] !== undefined) {
// return transition end event name
return transEndEvents[name];
}
}
// css transitions are not supported
return false;
})();
// class definition
var Looper = function(element, options) {
this.$element = $(element);
this.options = options;
this.looping = false;
// self-reference
var self = this;
// setup keyboard accessibility
this.$element.attr('tabindex', 0)
// use keydown, keypress not reliable in IE
.keydown(function(e){
// handle key
switch (e.which) {
// left arrow
case 37:
// go to previous item
self.prev();
break;
// right arrow
case 39:
// go to next item
self.next();
break;
// give control back to browser for other keys
default: return;
}
// prevent browser default action
e.preventDefault();
})
// ARIA
.find('.item').attr('aria-hidden', true);
// setup pause on hover
this.options.pause === 'hover' && this.$element
.on('mouseenter', $.proxy(this.loop, this))
.on('mouseleave', $.proxy(this.pause, this));
// trigger init event
this.$element.trigger('init');
};
// class prototype definition
Looper.prototype = {
/**
* Start auto-loop of items
* @param e
* @return Looper
*/
loop: function(e) {
if (!e) this.paused = false;
// check for interval
if (this.interval) {
// remove interval
clearInterval(this.interval);
this.interval = null;
}
// setup new loop interval
if (this.options.interval && !this.paused)
this.interval = setInterval($.proxy(this.next, this), this.options.interval);
// return reference to self for chaining
return this;
},
/**
* Pause auto-loop of items
* @param e
* @return Looper
*/
pause: function(e) {
if (!e) this.paused = true;
if (this.$element.find('.next, .prev').length && cssTransitionSupport) {
this.$element.trigger(cssTransitionSupport);
this.loop();
}
// remove interval
clearInterval(this.interval);
this.interval = null;
// return reference to self for chaining
return this;
},
/**
* Show next item
* @return Looper
*/
next: function() {
// return if looping
if (this.looping) return this;
// go to next item
return this.go('next');
},
/**
* Show previous item
* @return Looper
*/
prev: function() {
// return if looping
if (this.looping) return this;
// go to previous item
return this.go('prev');
},
/**
* Show item at specified position
* @param pos
* @return Looper
*/
to: function(pos) {
// return if looping
if (this.looping) return this;
// zero-base the position
--pos;
var // all items
$items = this.$element.find('.item'),
// active item
$active = $items.filter('.active'),
// active position
activePos = $items.index($active);
// return if position is out of range
if (pos > ($items.length - 1) || pos < 0) return this;
// if position is already active
if (activePos == pos)
// restart loop
return this.pause().loop();
// show item at position
return this.go($($items[pos]));
},
/**
* Show item
* @param to
* @return Looper
*/
go: function(to) {
// return if looping
if (this.looping) return this;
// all items
var $items = this.$element.find('.item');
// if no items, do nothing
if (!$items.length) return this;
// active item
var $active = $items.filter('.active'),
// active position
activePos = $items.index($active),
// next item to show
$next = typeof to == 'string' ? $active[to]() : to,
// next position
nextPos = $items.index($next),
// is there an auto-loop?
isLooping = this.interval,
// direction of next item
direction = typeof to == 'string'
? to
: ((activePos == -1 && nextPos == -1) || nextPos > activePos
? 'next'
: 'prev'),
// fallback if next item not found
fallback = direction == 'next' ? 'first' : 'last',
// self-reference
that = this,
// finish
complete = function(active, next, direction) {
// if not looping, already complete
if (!this.looping) return;
// set looping status to false
this.looping = false;
// update item classes
active.removeClass('active go ' + direction)
// update ARIA state
.attr('aria-hidden', true);
next.removeClass('go ' + direction).addClass('active')
// update ARIA state
.removeAttr('aria-hidden');
// custom event
var e = $.Event('shown', {
// related target is new active item
relatedTarget: next[0],
// related index is the index of the new active item
relatedIndex: $items.index(next)
});
// trigger shown event
this.$element.trigger(e);
};
// ensure next element
$next = $next && $next.length ? $next : $items[fallback]();
// return if next element is already active
if ($next.hasClass('active')) return this;
// custom event
var e = $.Event('show', {
// related target is next item to show
relatedTarget: $next[0],
relatedIndex: $items.index($next[0])
});
// trigger show event
this.$element.trigger(e);
// return if the event was canceled
if (e.isDefaultPrevented()) return this;
// set looping status to true
this.looping = true;
// if auto-looping, pause loop
if (isLooping) this.pause();
// if using a slide or cross-fade
if (this.$element.hasClass('slide') || this.$element.hasClass('xfade')) {
// if css transition support
if (cssTransitionSupport) {
// add direction class to active and next item
$next.addClass(direction);
$active.addClass('go ' + direction);
// force re-flow on next item
$next[0].offsetWidth;
// add go class to next item
$next.addClass('go');
// finish after transition
this.$element.one(cssTransitionSupport, function() {
// weird CSS transition when element is initially hidden
// may cause this event to fire twice with invalid $active
// element on first run
if (!$active.length) return;
complete.call(that, $active, $next, direction);
});
// ensure finish
setTimeout(function() {
complete.call(that, $active, $next, direction);
}, this.options.speed);
// no css transition support, use jQuery animation fallback
} else {
// setup animations
var active = {},
activeStyle,
next = {},
nextStyle;
// save original inline styles
activeStyle = $active.attr('style');
nextStyle = $next.attr('style');
// cross-fade
if (this.$element.hasClass('xfade')) {
active['opacity'] = 0;
next['opacity'] = 1;
$next.css('opacity', 0); // IE8
}
// slide
if (this.$element.hasClass('slide')) {
if (this.$element.hasClass('up')) {
active['top'] = direction == 'next' ? '-100%' : '100%';
next['top'] = 0;
} else if (this.$element.hasClass('down')) {
active['top'] = direction == 'next' ? '100%' : '-100%';
next['top'] = 0;
} else if (this.$element.hasClass('right')) {
active['left'] = direction == 'next' ? '100%' : '-100%';
next['left'] = 0;
} else {
active['left'] = direction == 'next' ? '-100%' : '100%';
next['left'] = 0;
}
}
$next.addClass(direction);
// do animations
$active.animate(active, this.options.speed);
$next.animate(next, this.options.speed, function(){
// finish
complete.call(that, $active, $next, direction);
// reset inline styles
$active.attr('style', activeStyle || '');
$next.attr('style', nextStyle || '');
});
}
// no animation
} else {
// finish
complete.call(that, $active, $next, direction);
}
// if auto-looping
if ((isLooping || (!isLooping && this.options.interval))
// and, no argument
&& (!to
// or, argument not equal to pause option
|| (typeof to == 'string' && to !== this.options.pause)
// or, argument is valid element object and pause option not equal to "to"
|| (to.length && this.options.pause !== 'to')))
// start/resume loop
this.loop();
// return reference to self for chaining
return this;
}
};
// plugin definition
$.fn.looper = function(option) {
// looper arguments
var looperArgs = arguments;
// for each matched element
return this.each(function() {
var $this = $(this),
looper = $this.data('looperjs'),
options = $.extend({}, $.fn.looper.defaults, $.isPlainObject(option) ? option : {}),
action = typeof option == 'string' ? option : option.looper,
args = option.args || (looperArgs.length > 1 && Array.prototype.slice.call(looperArgs, 1));
// ensure looper plugin
if (!looper) $this.data('looperjs', (looper = new Looper(this, options)));
// go to position if number
if (typeof option == 'number') looper.to(option);
// execute method if string
else if (action) {
// with arguments
if (args) looper[action].apply(looper, args.length ? args : ('' + args).split(','));
// without arguments
else looper[action]();
}
// if there's an interval, start the auto-loop
else if (options.interval) looper.loop()
// otherwise, go to first item in the loop
else looper.go();
});
};
// default options
$.fn.looper.defaults = {
// auto-loop interval
interval: 2000,
// when to pause auto-loop
pause: 'hover',
// css transition speed (must match css definition)
speed: 500
};
// constructor
$.fn.looper.Constructor = Looper;
// data api
$(function() {
// delegate click event on elements with data-looper attribute
$('body').on('click.looper', '[data-looper]', function(e) {
var $this = $(this);
// ignore the go method
if ($this.data('looper') == 'go') return;
// get element target via data (or href) attribute
var href, $target = $($this.data('target')
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')), //strip for ie7
// setup options
options = $.extend({}, $target.data(), $this.data());
// start looper plugin
$target.looper(options);
// prevent default event
e.preventDefault();
});
// auto-init plugin
$('[data-looper="go"]').each(function(){
var $this = $(this);
$this.looper($this.data());
});
});
})(jQuery, window, document);
我在插件文档中找不到任何有用的东西。