使用说明
轮播的HTML结构可以分为:容器、项目符号、轮播单元、左右的箭头
- 容器:需要data-ride="carousel"用于初始化;对应的id或class作为子元素的目标
- 项目符号:需要在"carousel-indicators"的容器中;data-target或href指向容器;data-slide-to指向对应的轮播单元;需要有"active"类保证在一开始就激活
- 单元:需要"item"作为类;需要"active"类保证在一开始就显示
- 箭头:data-target或hred指向容器;data-slide指向方向
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1" class=""></li>
<li data-target="#carousel-example-generic" data-slide-to="2" class=""></li>
</ol>
<div class="carousel-inner">
<div class="item active">
<img alt="First slide" src="http://37.media.tumblr.com/tumblr_m8tay0JcfG1qa42jro1_1280.jpg">
</div>
<div class="item">
<img alt="Second slide" src="http://37.media.tumblr.com/tumblr_m8tazfiVYJ1qa42jro1_1280.jpg">
</div>
<div class="item">
<img alt="Third slide" src="http://38.media.tumblr.com/tumblr_m8tb2rVsD31qa42jro1_1280.jpg">
</div>
</div>
<a class="left carousel-control" href="#carousel-example-generic" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" data-slide="next">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
</div>
核心思想
- 点击bullet、左右按钮、自动轮播最终都是调用slide(type, next)方法,传入方向和对应的下一个item
- slide里的逻辑
- 如果有bullet容器,则先完成bullet的切换
- 若不需要过渡效果,则将当前的item去除"active"类,下个"item"增加"active"类即可。若要过渡效果,则:
- 下个item增加"next"或"prev",使得item定位在轮播框的左侧或右侧
- 当前item增加"left"或"right",使得item左移或右移
- 下个item增加"left"或"right",完成左移或右移效果
初始化
// 为bullet和箭头绑定同一个点击处理事件
$(document)
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
// 页面加载完后,carousel初始化组件
$(window).on('load', function () {
$('[data-ride="carousel"]').each(function () {
var $carousel = $(this)
Plugin.call($carousel, $carousel.data())
})
})
具体分析
- slide方法
/**
* 判断方向,把next移入可视区内
* @param {string} type 移动的方向
* @param {object} next 将要被激活的item
* @return {object} Carousel实例
*/
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.item.active') // 当前激活的item
var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var that = this
if ($next.hasClass('active')) return (this.sliding = false)
var relatedTarget = $next[0]
var slideEvent = $.Event('slide.bs.carousel', {
relatedTarget: relatedTarget,
direction: direction
})
this.$element.trigger(slideEvent)
if (slideEvent.isDefaultPrevented()) return
this.sliding = true
isCycling && this.pause()
// 如果有bullet,则完成bullet的切换
if (this.$indicators.length) {
this.$indicators.find('.active').removeClass('active')
var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
$nextIndicator && $nextIndicator.addClass('active')
}
var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
if ($.support.transition && this.$element.hasClass('slide')) {
// 下个item,增加类如"next",使下个item定位在右边
$next.addClass(type)
$next[0].offsetWidth // force reflow
// 当前item,增加类如"left",使他左移
$active.addClass(direction)
// 下个item再增加类如"left",使得他左移
$next.addClass(direction)
$active
.one('bsTransitionEnd', function () {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function () {
that.$element.trigger(slidEvent)
}, 0)
})
.emulateTransitionEnd(Carousel.TRANSITION_DURATION)
} else {
// 若不支持过渡,只是当初的当前item解除激活,激活下个item
$active.removeClass('active')
$next.addClass('active')
this.sliding = false
this.$element.trigger(slidEvent)
}
isCycling && this.cycle()
return this
}
总结:
- 通过方向的类"left"或"right",位置的类"next"或"prev"的配合,完成轮播的切换效果