bootstrap之carousel
来源:互联网 发布:linux两个mysql 编辑:程序博客网 时间:2024/05/19 16:07
一、前言
这节介绍下carousel(轮播)模块的源码实现。
二、源码
1、carousel.less
// // Carousel(图片轮播) // -------------------------------------------------- // Wrapper for the slide container and indicators(轮播图容器) .carousel { position: relative; } // 轮播图片播放区 .carousel-inner { position: relative; overflow: hidden; width: 100%; > .item { display: none; position: relative; .transition(.6s ease-in-out left); // Account for jankitude on images > img, > a > img { &:extend(.img-responsive); line-height: 1; } // WebKit CSS3 transforms for supported devices @media all and (transform-3d), (-webkit-transform-3d) { .transition-transform(~'0.6s ease-in-out'); .backface-visibility(~'hidden'); .perspective(1000px); &.next, &.active.right { .translate3d(100%, 0, 0); left: 0; } &.prev, &.active.left { .translate3d(-100%, 0, 0); left: 0; } &.next.left, &.prev.right, &.active { .translate3d(0, 0, 0); left: 0; } } } > .active, > .next, > .prev { display: block; } > .active { left: 0; } > .next, > .prev { position: absolute; top: 0; width: 100%; } > .next { left: 100%; } > .prev { left: -100%; } > .next.left, > .prev.right { left: 0; } > .active.left { left: -100%; } > .active.right { left: 100%; } } // Left/right controls for nav(轮播图片控制器) // --------------------------- .carousel-control { position: absolute; top: 0; left: 0; bottom: 0; width: @carousel-control-width; .opacity(@carousel-control-opacity); font-size: @carousel-control-font-size; color: @carousel-control-color; text-align: center; text-shadow: @carousel-text-shadow; background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug // We can't have this transition here because WebKit cancels the carousel // animation if you trip this while in the middle of another animation. // Set gradients for backgrounds &.left { #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001)); } &.right { left: auto; right: 0; #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5)); } // Hover/focus state &:hover, &:focus { outline: 0; color: @carousel-control-color; text-decoration: none; .opacity(.9); } // Toggles .icon-prev, .icon-next, .glyphicon-chevron-left, .glyphicon-chevron-right { position: absolute; top: 50%; margin-top: -10px; z-index: 5; display: inline-block; } .icon-prev, .glyphicon-chevron-left { left: 50%; margin-left: -10px; } .icon-next, .glyphicon-chevron-right { right: 50%; margin-right: -10px; } .icon-prev, .icon-next { width: 20px; height: 20px; line-height: 1; font-family: serif; } .icon-prev { &:before { content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) } } .icon-next { &:before { content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) } } } // Optional indicator pips(轮播图片计数器) // // Add an unordered list with the following class and add a list item for each // slide your carousel holds. .carousel-indicators { position: absolute; bottom: 10px; left: 50%; z-index: 15; width: 60%; margin-left: -30%; padding-left: 0; list-style: none; text-align: center; li { display: inline-block; width: 10px; height: 10px; margin: 1px; text-indent: -999px; border: 1px solid @carousel-indicator-border-color; border-radius: 10px; cursor: pointer; // IE8-9 hack for event handling // // Internet Explorer 8-9 does not support clicks on elements without a set // `background-color`. We cannot use `filter` since that's not viewed as a // background color by the browser. Thus, a hack is needed. // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer // // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we // set alpha transparency for the best results possible. background-color: #000 \9; // IE8 background-color: rgba(0,0,0,0); // IE9 } .active { margin: 0; width: 12px; height: 12px; background-color: @carousel-indicator-active-bg; } } // Optional captions(图片对应标题和描述内容) // ----------------------------- // Hidden by default for smaller viewports .carousel-caption { position: absolute; left: 15%; right: 15%; bottom: 20px; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: @carousel-caption-color; text-align: center; text-shadow: @carousel-text-shadow; & .btn { text-shadow: none; // No shadow for button elements in carousel-caption } } // Scale up controls for tablets and up(对于大屏设备放大一点控制器) @media screen and (min-width: @screen-sm-min) { // Scale up the controls a smidge(一点点) .carousel-control { .glyphicon-chevron-left, .glyphicon-chevron-right, .icon-prev, .icon-next { width: (@carousel-control-font-size * 1.5); height: (@carousel-control-font-size * 1.5); margin-top: (@carousel-control-font-size / -2); font-size: (@carousel-control-font-size * 1.5); } .glyphicon-chevron-left, .icon-prev { margin-left: (@carousel-control-font-size / -2); } .glyphicon-chevron-right, .icon-next { margin-right: (@carousel-control-font-size / -2); } } // Show and left align the captions .carousel-caption { left: 20%; right: 20%; padding-bottom: 30px; } // Move up the indicators .carousel-indicators { bottom: 20px; } }
2、carousel.js
/* ======================================================================== * Bootstrap: carousel.js v3.3.7(图片轮播) * http://getbootstrap.com/javascript/#carousel * ======================================================================== * Copyright 2011-2016 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CAROUSEL CLASS DEFINITION // ========================= var Carousel = function (element, options) { this.$element = $(element); this.$indicators = this.$element.find('.carousel-indicators'); this.options = options; this.paused = null; this.sliding = null; // 判断是否正在轮播项滚动 this.interval = null; // 轮播循环播放定时器 this.$active = null; this.$items = null; // 如果options.keyboard == true,则监听键盘事件 this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)); // 不是移动设备(不存在ontouchstart事件),那么当options.pause == 'hover'时实现鼠标的悬浮暂停 this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) }; Carousel.VERSION = '3.3.7'; Carousel.TRANSITION_DURATION = 600; Carousel.DEFAULTS = { interval: 5000, pause: 'hover', wrap: true, keyboard: true }; // 键盘事件,做出相应操作 Carousel.prototype.keydown = function (e) { if (/input|textarea/i.test(e.target.tagName)) return; switch (e.which) { case 37: this.prev(); break; case 39: this.next(); break; default: return } e.preventDefault() }; // 循环轮播,清除定时器并重新设置定时器 Carousel.prototype.cycle = function (e) { e || (this.paused = false); this.interval && clearInterval(this.interval); this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)); return this }; // 获取轮播项索引值 Carousel.prototype.getItemIndex = function (item) { this.$items = item.parent().children('.item'); return this.$items.index(item || this.$active) }; // 获取方向上的轮播项 Carousel.prototype.getItemForDirection = function (direction, active) { var activeIndex = this.getItemIndex(active); var willWrap = (direction == 'prev' && activeIndex === 0) || (direction == 'next' && activeIndex == (this.$items.length - 1)); if (willWrap && !this.options.wrap) return active; var delta = direction == 'prev' ? -1 : 1; // 如果itemIndex为负数-1,不需要做处理,因为eq函数参数为负数时从集合最后一个元素开始倒数 var itemIndex = (activeIndex + delta) % this.$items.length; return this.$items.eq(itemIndex) }; // 滚动到指定轮播项 Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')); if (pos > (this.$items.length - 1) || pos < 0) return; // 如果轮播图正在滚动切换,那么滚动到指定轮播项需要等到滚动切换结束(即监听到slid.bs.carousel)时才能继续操作 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }); // yes, "slid" if (activeIndex == pos) return this.pause().cycle(); return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) }; // 暂停轮播,清除定时器 Carousel.prototype.pause = function (e) { e || (this.paused = true); // 如果刚好为轮播添加了next/prev类即将开始滚动并且浏览器支持动画,鼠标移入,那么直接触发动画结束自定义事件 if (this.$element.find('.next, .prev').length && $.support.transition) { this.$element.trigger($.support.transition.end); this.cycle(true) } this.interval = clearInterval(this.interval); return this }; // 下一个轮播图 Carousel.prototype.next = function () { // 如果轮播图正在滚动切换,那么上下轮播切换不做任何操作 if (this.sliding) return; return this.slide('next') }; // 上一个轮播图 Carousel.prototype.prev = function () { if (this.sliding) return; return this.slide('prev') }; // 滚动函数 Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active'); 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(); // 为计数器切换active类 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')) { $next.addClass(type); $next[0].offsetWidth // force reflow $active.addClass(direction); $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 { $active.removeClass('active'); $next.addClass('active'); this.sliding = false; this.$element.trigger(slidEvent) } isCycling && this.cycle(); return this }; // CAROUSEL PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this); var data = $this.data('bs.carousel'); var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option); var action = typeof option == 'string' ? option : options.slide; if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))); // js方法直接触发轮播,跳转到指定轮播页 if (typeof option == 'number') data.to(option); // 在点击上、下一个时触发轮播 else if (action) data[action](); // 初始化加载,在data-ride="carousel"且data-interval==true情况下触发轮播 else if (options.interval) data.pause().cycle() }) } var old = $.fn.carousel; $.fn.carousel = Plugin; $.fn.carousel.Constructor = Carousel; // CAROUSEL NO CONFLICT // ==================== $.fn.carousel.noConflict = function () { $.fn.carousel = old; return this }; // CAROUSEL DATA-API // ================= var clickHandler = function (e) { var href; var $this = $(this); var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')); // strip for ie7 // 如果目标元素没有carousel类,说明不是carousel容器,不做任何处理 if (!$target.hasClass('carousel')) return; var options = $.extend({}, $target.data(), $this.data()); var slideIndex = $this.attr('data-slide-to'); if (slideIndex) options.interval = false; Plugin.call($target, options); if (slideIndex) { $target.data('bs.carousel').to(slideIndex) } // 防止使用a标签改变了链接地址等,阻止默认事件发生 e.preventDefault() }; $(document) .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler); $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { var $carousel = $(this) Plugin.call($carousel, $carousel.data()) }) }) }(jQuery);
三、应用 & 源码分析
1、应用
<div id="myCarousel" class="carousel slide"> <!-- 轮播(Carousel)指标 --> <ol class="carousel-indicators"> <li data-target="#myCarousel" data-slide-to="0" class="active"></li> <li data-target="#myCarousel" data-slide-to="1"></li> <li data-target="#myCarousel" data-slide-to="2"></li> </ol> <!-- 轮播(Carousel)项目 --> <div class="carousel-inner"> <div class="item active"> <img src="/wp-content/uploads/2014/07/slide1.png" alt="First slide"> </div> <div class="item"> <img src="/wp-content/uploads/2014/07/slide2.png" alt="Second slide"> </div> <div class="item"> <img src="/wp-content/uploads/2014/07/slide3.png" alt="Third slide"> </div> </div> <!-- 轮播(Carousel)导航 --> <a class="carousel-control left" href="#myCarousel" data-slide="prev">‹</a> <a class="carousel-control right" href="#myCarousel" data-slide="next">›</a> <!-- 控制按钮 --> <div style="text-align:center;"> <input type="button" class="btn start-slide" value="Start"> <input type="button" class="btn pause-slide" value="Pause"> <input type="button" class="btn prev-slide" value="Previous Slide"> <input type="button" class="btn next-slide" value="Next Slide"> <input type="button" class="btn slide-one" value="Slide 1"> <input type="button" class="btn slide-two" value="Slide 2"> <input type="button" class="btn slide-three" value="Slide 3"> </div> </div> <script> $(function(){ // 初始化轮播 $(".start-slide").click(function(){ $("#myCarousel").carousel('cycle'); }); // 停止轮播 $(".pause-slide").click(function(){ $("#myCarousel").carousel('pause'); }); // 循环轮播到上一个项目 $(".prev-slide").click(function(){ $("#myCarousel").carousel('prev'); }); // 循环轮播到下一个项目 $(".next-slide").click(function(){ $("#myCarousel").carousel('next'); }); // 循环轮播到某个特定的帧 $(".slide-one").click(function(){ $("#myCarousel").carousel(0); }); $(".slide-two").click(function(){ $("#myCarousel").carousel(1); }); $(".slide-three").click(function(){ $("#myCarousel").carousel(2); }); }); </script>
2、源码分析
2.1、carousel.less
1、carousel(相对定位) 分为 carousel-indicators(指示器)、carousel-inner(轮播项目)、carousel-control(轮播导航);
2、为 carousel-inner 内的 item(轮播项)设置left、active、right 等样式,操作 left 或者 translate3d(如果支持动画效果的话)设置轮播项的位置;
3、carousel-control(绝对定位) 分为 left、right 两种状态,并设置 hover、focus、icon 等样式;
4、carousel-indicators、carousel-caption均为绝对布局,并为大屏设置做了一点调整
2.2、modal.js
1、通过 data-ride=”carousel” 或 $(“#myCarousel”).carousel() 进行轮播初始化;
2、监听 data-slide-to 和 data-slide 属性值或者调用 carousel(option) 方法,做出相应滚动操作;
3、支持键盘操作,监听键盘事件,执行 keydown 函数滚动;
4、最为核心的方法是 slide,先找到当前页,然后获取下一页和滚动方向,通过设置切换轮播项的 class 达到滚动的目的
阅读全文
0 0
- Bootstrap学习之Carousel
- bootstrap之carousel
- Bootstrap之轮播 carousel
- Bootstrap Carousel
- bootstrap carousel
- Bootstrap 简单认识之Carousel组件
- Bootstrap的js插件之轮播(carousel)
- Bootstrap之Carousel不能自动播放的解决办法
- bootstrap之 carousel.js轮播插件源码分析
- bootstrap中的carousel插件
- Bootstrap Carousel Plugin
- carousel(Bootstrap)
- bootstrap 修改carousel 样式
- bootstrap 2-滚动广告Carousel
- Bootstrap之Carousel不能自动播放的解决办法,支持左右滑动手势
- angular js轮播图 (Carousel (ui.bootstrap.carousel))
- sencha touch之carousel
- 【Bootstrap】图片轮播组件Carousel
- 【Python融于生活】之我想要保存QQ邮箱富途的附件
- 也许这些电影真该看看
- 深入解析Linux 常用命令--alias
- 压缩指令ubuntu
- netty 服务端作为客户端跳转请求服务端
- bootstrap之carousel
- 关于微信支付以及获取签名的正确方法
- 简单的圆形三角形
- 187. Repeated DNA Sequences
- 一位资深程序员大牛给予Java的学习路线建议
- 【论文笔记】视频物体检测(VID)系列 FGFA:Flow-Guided Feature Aggregation for Video Object Detection
- netty源码分析(十七)Netty线程模型深度解读与架构设计原则
- linux poll()系统调用函数介绍
- jpbm数据表结构