carousel.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /**
  2. @Name:layui.carousel 轮播模块
  3. @Author:贤心
  4. @License:MIT
  5. */
  6. layui.define('jquery', function(exports){
  7. "use strict";
  8. var $ = layui.$
  9. ,hint = layui.hint()
  10. ,device = layui.device()
  11. //外部接口
  12. ,carousel = {
  13. config: {} //全局配置项
  14. //设置全局项
  15. ,set: function(options){
  16. var that = this;
  17. that.config = $.extend({}, that.config, options);
  18. return that;
  19. }
  20. //事件监听
  21. ,on: function(events, callback){
  22. return layui.onevent.call(this, MOD_NAME, events, callback);
  23. }
  24. }
  25. //字符常量
  26. ,MOD_NAME = 'carousel', ELEM = '.layui-carousel', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled'
  27. ,ELEM_ITEM = '>*[carousel-item]>*', ELEM_LEFT = 'layui-carousel-left', ELEM_RIGHT = 'layui-carousel-right', ELEM_PREV = 'layui-carousel-prev', ELEM_NEXT = 'layui-carousel-next', ELEM_ARROW = 'layui-carousel-arrow', ELEM_IND = 'layui-carousel-ind'
  28. //构造器
  29. ,Class = function(options){
  30. var that = this;
  31. that.config = $.extend({}, that.config, carousel.config, options);
  32. that.render();
  33. };
  34. //默认配置
  35. Class.prototype.config = {
  36. width: '600px'
  37. ,height: '280px'
  38. ,full: false //是否全屏
  39. ,arrow: 'hover' //切换箭头默认显示状态:hover/always/none
  40. ,indicator: 'inside' //指示器位置:inside/outside/none
  41. ,autoplay: true //是否自动切换
  42. ,interval: 3000 //自动切换的时间间隔,不能低于800ms
  43. ,anim: '' //动画类型:default/updown/fade
  44. ,trigger: 'click' //指示器的触发方式:click/hover
  45. ,index: 0 //初始开始的索引
  46. };
  47. //轮播渲染
  48. Class.prototype.render = function(){
  49. var that = this
  50. ,options = that.config;
  51. options.elem = $(options.elem);
  52. if(!options.elem[0]) return;
  53. that.elemItem = options.elem.find(ELEM_ITEM);
  54. if(options.index < 0) options.index = 0;
  55. if(options.index >= that.elemItem.length) options.index = that.elemItem.length - 1;
  56. if(options.interval < 800) options.interval = 800;
  57. //是否全屏模式
  58. if(options.full){
  59. options.elem.css({
  60. position: 'fixed'
  61. ,width: '100%'
  62. ,height: '100%'
  63. ,zIndex: 9999
  64. });
  65. } else {
  66. options.elem.css({
  67. width: options.width
  68. ,height: options.height
  69. });
  70. }
  71. options.elem.attr('lay-anim', options.anim);
  72. //初始焦点状态
  73. that.elemItem.eq(options.index).addClass(THIS);
  74. //指示器等动作
  75. if(that.elemItem.length <= 1) return;
  76. that.indicator();
  77. that.arrow();
  78. that.autoplay();
  79. that.events();
  80. };
  81. //重置轮播
  82. Class.prototype.reload = function(options){
  83. var that = this;
  84. clearInterval(that.timer);
  85. that.config = $.extend({}, that.config, options);
  86. that.render();
  87. };
  88. //获取上一个等待条目的索引
  89. Class.prototype.prevIndex = function(){
  90. var that = this
  91. ,options = that.config;
  92. var prevIndex = options.index - 1;
  93. if(prevIndex < 0){
  94. prevIndex = that.elemItem.length - 1;
  95. }
  96. return prevIndex;
  97. };
  98. //获取下一个等待条目的索引
  99. Class.prototype.nextIndex = function(){
  100. var that = this
  101. ,options = that.config;
  102. var nextIndex = options.index + 1;
  103. if(nextIndex >= that.elemItem.length){
  104. nextIndex = 0;
  105. }
  106. return nextIndex;
  107. };
  108. //索引递增
  109. Class.prototype.addIndex = function(num){
  110. var that = this
  111. ,options = that.config;
  112. num = num || 1;
  113. options.index = options.index + num;
  114. //index不能超过轮播总数量
  115. if(options.index >= that.elemItem.length){
  116. options.index = 0;
  117. }
  118. };
  119. //索引递减
  120. Class.prototype.subIndex = function(num){
  121. var that = this
  122. ,options = that.config;
  123. num = num || 1;
  124. options.index = options.index - num;
  125. //index不能超过轮播总数量
  126. if(options.index < 0){
  127. options.index = that.elemItem.length - 1;
  128. }
  129. };
  130. //自动轮播
  131. Class.prototype.autoplay = function(){
  132. var that = this
  133. ,options = that.config;
  134. if(!options.autoplay) return;
  135. clearInterval(that.timer);
  136. that.timer = setInterval(function(){
  137. that.slide();
  138. }, options.interval);
  139. };
  140. //箭头
  141. Class.prototype.arrow = function(){
  142. var that = this
  143. ,options = that.config;
  144. //模板
  145. var tplArrow = $([
  146. '<button class="layui-icon '+ ELEM_ARROW +'" lay-type="sub">'+ (options.anim === 'updown' ? '&#xe619;' : '&#xe603;') +'</button>'
  147. ,'<button class="layui-icon '+ ELEM_ARROW +'" lay-type="add">'+ (options.anim === 'updown' ? '&#xe61a;' : '&#xe602;') +'</button>'
  148. ].join(''));
  149. //预设基础属性
  150. options.elem.attr('lay-arrow', options.arrow);
  151. //避免重复插入
  152. if(options.elem.find('.'+ELEM_ARROW)[0]){
  153. options.elem.find('.'+ELEM_ARROW).remove();
  154. };
  155. options.elem.append(tplArrow);
  156. //事件
  157. tplArrow.on('click', function(){
  158. var othis = $(this)
  159. ,type = othis.attr('lay-type')
  160. that.slide(type);
  161. });
  162. };
  163. //指示器
  164. Class.prototype.indicator = function(){
  165. var that = this
  166. ,options = that.config;
  167. //模板
  168. var tplInd = that.elemInd = $(['<div class="'+ ELEM_IND +'"><ul>'
  169. ,function(){
  170. var li = [];
  171. layui.each(that.elemItem, function(index){
  172. li.push('<li'+ (options.index === index ? ' class="layui-this"' : '') +'></li>');
  173. });
  174. return li.join('');
  175. }()
  176. ,'</ul></div>'].join(''));
  177. //预设基础属性
  178. options.elem.attr('lay-indicator', options.indicator);
  179. //避免重复插入
  180. if(options.elem.find('.'+ELEM_IND)[0]){
  181. options.elem.find('.'+ELEM_IND).remove();
  182. };
  183. options.elem.append(tplInd);
  184. if(options.anim === 'updown'){
  185. tplInd.css('margin-top', -(tplInd.height()/2));
  186. }
  187. //事件
  188. tplInd.find('li').on(options.trigger === 'hover' ? 'mouseover' : options.trigger, function(){
  189. var othis = $(this)
  190. ,index = othis.index();
  191. if(index > options.index){
  192. that.slide('add', index - options.index);
  193. } else if(index < options.index){
  194. that.slide('sub', options.index - index);
  195. }
  196. });
  197. };
  198. //滑动切换
  199. Class.prototype.slide = function(type, num){
  200. var that = this
  201. ,elemItem = that.elemItem
  202. ,options = that.config
  203. ,thisIndex = options.index
  204. ,filter = options.elem.attr('lay-filter');
  205. if(that.haveSlide) return;
  206. //滑动方向
  207. if(type === 'sub'){
  208. that.subIndex(num);
  209. elemItem.eq(options.index).addClass(ELEM_PREV);
  210. setTimeout(function(){
  211. elemItem.eq(thisIndex).addClass(ELEM_RIGHT);
  212. elemItem.eq(options.index).addClass(ELEM_RIGHT);
  213. }, 50);
  214. } else { //默认递增滑
  215. that.addIndex(num);
  216. elemItem.eq(options.index).addClass(ELEM_NEXT);
  217. setTimeout(function(){
  218. elemItem.eq(thisIndex).addClass(ELEM_LEFT);
  219. elemItem.eq(options.index).addClass(ELEM_LEFT);
  220. }, 50);
  221. };
  222. //移除过度类
  223. setTimeout(function(){
  224. elemItem.removeClass(THIS + ' ' + ELEM_PREV + ' ' + ELEM_NEXT + ' ' + ELEM_LEFT + ' ' + ELEM_RIGHT);
  225. elemItem.eq(options.index).addClass(THIS);
  226. that.haveSlide = false; //解锁
  227. }, 300);
  228. //指示器焦点
  229. that.elemInd.find('li').eq(options.index).addClass(THIS)
  230. .siblings().removeClass(THIS);
  231. that.haveSlide = true;
  232. layui.event.call(this, MOD_NAME, 'change('+ filter +')', {
  233. index: options.index
  234. ,prevIndex: thisIndex
  235. ,item: elemItem.eq(options.index)
  236. });
  237. };
  238. //事件处理
  239. Class.prototype.events = function(){
  240. var that = this
  241. ,options = that.config;
  242. if(options.elem.data('haveEvents')) return;
  243. //移入移出容器
  244. options.elem.on('mouseenter', function(){
  245. clearInterval(that.timer);
  246. }).on('mouseleave', function(){
  247. that.autoplay();
  248. });
  249. options.elem.data('haveEvents', true);
  250. };
  251. //核心入口
  252. carousel.render = function(options){
  253. var inst = new Class(options);
  254. return inst;
  255. };
  256. exports(MOD_NAME, carousel);
  257. });