zhiqim_slider.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。
  3. *
  4. * 指定登记&发行网站: https://www.zhiqim.com/ 欢迎加盟知启蒙,[编程有你,知启蒙一路随行]。
  5. *
  6. * 本文采用《知启蒙登记发行许可证》,除非符合许可证,否则不可使用该文件!
  7. * 1、您可以免费使用、修改、合并、出版发行和分发,再授权软件、软件副本及衍生软件;
  8. * 2、您用于商业用途时,必须在原作者指定的登记网站,按原作者要求进行登记;
  9. * 3、您在使用、修改、合并、出版发行和分发时,必须包含版权声明、许可声明,及保留原作者的著作权、商标和专利等知识产权;
  10. * 4、您在互联网、移动互联网等大众网络下发行和分发再授权软件、软件副本及衍生软件时,必须在原作者指定的发行网站进行发行和分发;
  11. * 5、您可以在以下链接获取一个完整的许可证副本。
  12. *
  13. * 许可证链接:http://zhiqim.org/licenses/zhiqim_register_publish_license.htm
  14. *
  15. * 除非法律需要或书面同意,软件由原始码方式提供,无任何明示或暗示的保证和条件。详见完整许可证的权限和限制。
  16. */
  17. +(function(Z)
  18. {
  19. /****************************************/
  20. //“轮播图”
  21. /****************************************/
  22. // 1、配置举例:
  23. // <ul id="zoomSlider">
  24. // <li><img src="https://www.zhiqim.com/document/inc/www/tutorial/guest.jpg"></li>
  25. // <li><img src="https://www.zhiqim.com/document/inc/www/tutorial/guest.jpg"></li>
  26. // <li><img src="https://www.zhiqim.com/document/inc/www/tutorial/guest.jpg"></li>
  27. // <li><img src="https://www.zhiqim.com/document/inc/www/tutorial/guest.jpg"></li>
  28. // </ul>
  29. //
  30. // <script>
  31. // var newZslider = new Z.Zslider();
  32. // newZslider.elem = Z("#zoomSlider"); // 列表对象
  33. // newZslider.width = -1; // 容器宽度,默认为 -1,动态计算
  34. // newZslider.hasBtn = true; // 左右按钮是否显示,默认为 true
  35. // newZslider.slideStyle = "slide"; // 播放类型:slide(滑动)fade(渐显),默认为 slide
  36. // newZslider.tabStyle = "disc"; // tab 菜单类型:disc(实心圆点)circle(空心圆)square(实心方块),默认为 disc
  37. // newZslider.tabEvent = "click"; // tab 菜单触发方式:click(点击)hover(悬浮),默认为 click
  38. // newZslider.execute();
  39. // </script>
  40. Z.Zslider = Z.Class.newInstance();
  41. Z.Zslider.prototype =
  42. {
  43. //start of Z.Zslider.prototype
  44. defaults:
  45. {//定义
  46. elem: null, // 列表对象
  47. width: 0, // 容器宽度
  48. height: 300, // 容器高度
  49. hasBtn: true, // 左右按钮是否显示,默认为 true
  50. doResize: false, // 是否自适应缩放
  51. slideStyle: "slide", // 播放类型:slide(滑动)fade(渐显),默认为 slide
  52. tabStyle: "disc", // tab 菜单类型:disc(实心圆点)circle(空心圆)square(实心方块),默认为 disc
  53. tabEvent: "click", // tab 菜单触发方式:click(点击)hover(悬浮)
  54. playGapless: true, // 无缝轮播
  55. playAuto: true, // 设定自动滚动
  56. playSpeed: 4000, // 播放间隔
  57. playDuration: 800, // 动画时长
  58. },
  59. init: function()
  60. {//初始化
  61. },
  62. validate: function()
  63. {//验证参数
  64. this.$ul = Z.$elem(this.elem, "Z.Zslider");
  65. if (!Z.AR.contains(["slide", "fade"], this.slideStyle))
  66. return false;
  67. if (!Z.AR.contains(["disc", "circle", "square"], this.tabStyle))
  68. return false;
  69. if (!Z.AR.contains(["click", "hover"], this.tabEvent))
  70. return false;
  71. return true;
  72. },
  73. execute: function()
  74. {//执行
  75. //1:检验、设置参数
  76. if (!this.validate())
  77. return;
  78. this.height = this.getRectSize(this.height, this.$ul.offsetHeight());
  79. if (this.width)
  80. {
  81. this.doResize = false;
  82. this.width = this.getRectSize(this.width, this.$ul.offsetWidth());
  83. } else {
  84. this.width = Math.round(this.$ul.offsetWidth());
  85. }
  86. if (this.playSpeed < this.playDuration){
  87. this.playSpeed = this.playDuration;
  88. }
  89. if (!this.width || !this.height)
  90. return Z.alert("[Z.Zslider]参数[width][height]设置有误!");
  91. //2:重新组装排版
  92. var wrapHtml = '<div class="z-slider z-relative" style="width:'+this.width+'px;height:'+this.height+'px;">';
  93. wrapHtml += '<div class="z-sliderList z-absolute z-w100p z-h100p z-overflow-hidden"></div>';
  94. wrapHtml += '<div class="z-sliderTab z-sliderTab-'+this.tabStyle+' z-w100p z-h0 z-absolute z-l0 z-b0 z-text-center"></div>';
  95. wrapHtml += '</div>';
  96. this.$wrap = Z(wrapHtml).insertAfter(this.$ul);
  97. this.$list = this.$wrap.find(".z-sliderList").append(this.$ul);
  98. this.$$items = this.$ul.find("li");
  99. this.$tab = this.$wrap.find(".z-sliderTab");
  100. this.length = this.$$items.length;
  101. //3:左右操作按钮
  102. if (this.hasBtn){
  103. var btnHtml = '<div class="z-sliderBtn z-w100p z-h0 z-absolute z-l0 z-text-center">';
  104. btnHtml += '<div class="z-sliderBtn-prev z-absolute z-l0 z-t0 z-w60 z-h100 z-pointer">';
  105. btnHtml += '<i class="z-font z-text-gray z-arrowhead-left z-absolute z-l0 z-r0 z-mg-lr-auto"></i>';
  106. btnHtml += '</div>';
  107. btnHtml += '<div class="z-sliderBtn-next z-absolute z-r0 z-t0 z-w60 z-h100 z-pointer">';
  108. btnHtml += '<i class="z-font z-text-gray z-arrowhead-right z-absolute z-l0 z-r0 z-mg-lr-auto"></i>';
  109. btnHtml += '</div>';
  110. btnHtml += '</div>';
  111. this.$btn = Z(btnHtml).appendTo(this.$wrap);
  112. this.$btn.find(".z-sliderBtn-prev").on("click", this.sliderPrev, this);
  113. this.$btn.find(".z-sliderBtn-next").on("click", this.sliderNext, this);
  114. }
  115. //4:底部导航 tab 按钮
  116. var tabsHtml = "";
  117. var i = 0;
  118. for (i;i < this.length;i++){
  119. tabsHtml += '<div></div>';
  120. }
  121. this.$tab[0].insertAdjacentHTML("beforeend",tabsHtml);
  122. this.$$tabs = this.$tab.find("div");
  123. Z(this.$$tabs[0]).addClass("z-active");
  124. //5:list 样式
  125. if (this.slideStyle === "slide")
  126. {//滑动处理
  127. this.$ul.css("width", this.length * this.width).css("transition-duration",this.playDuration+"ms");
  128. var $item;
  129. for (i = 0;i < this.length;i++)
  130. {
  131. $item = this.$$items[i];
  132. Z($item).css({
  133. "width": this.width,
  134. "transform": "translate3d(" + i * this.width + "px,0,0)"
  135. });
  136. if (i === 0){
  137. this.$firstClone = Z($item.cloneNode("deep")).css("transform","translate3d(" + this.length * this.width + "px,0,0)");
  138. }
  139. if (i === this.length - 1){
  140. this.$lastClone = Z($item.cloneNode("deep")).css("transform","translate3d(-" + this.width + "px,0,0)");
  141. }
  142. }
  143. //插入克隆体
  144. this.$firstClone.appendTo(this.$ul);
  145. this.$lastClone.appendTo(this.$ul);
  146. //滑动结束,判断是否可滑动
  147. this.$ul.on(this.transitionFixed(), this.slideEnd, this);
  148. }
  149. else if (this.slideStyle === "fade")
  150. {//渐显处理
  151. this.$$items.css("top","0").css("transition-property","opacity,top");
  152. Z(this.$$items[0]).css("opacity",1).siblings("li").css("opacity",0).addClass("z-hide");
  153. //渐隐结束,隐藏该元素
  154. this.$$items.on(this.transitionFixed(), this.fadeEnd, this);
  155. }
  156. this.$$items.css("transition-duration",this.playDuration+"ms");
  157. Z(this.$$items[0]).addClass("z-active");
  158. //6:绑定事件
  159. var tabEvent = (this.tabEvent === "click")?"click":"mouseenter";
  160. this.$$tabs.on(tabEvent, this.tabTrigger, this);
  161. this.$wrap.on("mouseenter", this.wrapEnter, this);
  162. this.$wrap.on("mouseleave", this.wrapLeave, this);
  163. if (this.doResize)
  164. Z(window).on('resize', this.resize, this);
  165. //7:开始执行动画
  166. this.autoPlay();
  167. },
  168. autoPlay: function()
  169. {//自动播放
  170. if(this.playAuto && !this.playAutoTimer)
  171. this.playAutoTimer = setInterval(this.sliderNext, this.playSpeed, null, this);
  172. },
  173. wrapEnter: function()
  174. {
  175. if(this.$btn){
  176. this.$btn.addClass("z-active");
  177. }
  178. //清除自动
  179. clearInterval(this.playAutoTimer);
  180. this.playAutoTimer = null;
  181. },
  182. wrapLeave: function()
  183. {
  184. if(this.$btn){
  185. this.$btn.removeClass("z-active");
  186. }
  187. this.autoPlay();
  188. },
  189. sliderNext: function(event, thisObj)
  190. {//后一个展示
  191. thisObj = thisObj || this;
  192. thisObj.sliderPlay(1);
  193. },
  194. sliderStay: function ()
  195. {//保持展示
  196. this.sliderPlay(0);
  197. },
  198. sliderPrev: function()
  199. {//前一个展示
  200. this.sliderPlay(-1);
  201. },
  202. sliderPlay: function(step)
  203. {//播放方法
  204. if (this.sliding){
  205. return;
  206. }
  207. this[this.slideStyle+"ToPlay"](step);
  208. },
  209. slideToPlay: function(step)
  210. {//滑动方法
  211. this.sliding = true;
  212. step = +step;
  213. var $activeItem = this.$ul.find(".z-active");
  214. var activeIndex = Z.AR.indexOf(this.$$items, $activeItem[0]);
  215. $activeItem.removeClass("z-active");
  216. //即将展示对象的索引值
  217. var shouldIndex = activeIndex + step;
  218. if (shouldIndex >= this.length) shouldIndex = 0;
  219. if (shouldIndex <= -1) shouldIndex = this.length - 1;
  220. //定义定位
  221. var $shouldActive = Z(this.$$items[shouldIndex]);
  222. var ulTrans = -shouldIndex * this.width;
  223. //逐步滚动 |step| = 1 到边缘时,实现无缝滚动
  224. if (this.playGapless)
  225. {
  226. if (step === 1 && shouldIndex === 0) {
  227. $shouldActive = this.$firstClone;
  228. ulTrans = -this.length * this.width;
  229. }
  230. if (step === -1 && shouldIndex === this.length - 1) {
  231. $shouldActive = this.$lastClone;
  232. ulTrans = this.width;
  233. }
  234. }
  235. // 新定位
  236. this.$ul.css("transform", "translate3d("+ulTrans+"px,0,0)");
  237. if (this.$ul.css("transition-property") === "none"){
  238. this.$ul.css("transition-property", "transform");
  239. }
  240. $shouldActive.addClass("z-active");
  241. //tab 展示
  242. Z(this.$$tabs[shouldIndex]).addClass("z-active").siblings("div").removeClass("z-active");
  243. },
  244. fadeToPlay: function(step)
  245. {//渐显方法
  246. step = +step;
  247. var $activeItem = this.$ul.find(".z-active");
  248. var activeIndex = Z.AR.indexOf(this.$$items, $activeItem[0]);
  249. $activeItem.removeClass("z-active").css("opacity",0).css("top",-10);
  250. var shouldIndex = activeIndex + step;
  251. if (shouldIndex >= this.length) shouldIndex = 0;
  252. if (shouldIndex <= -1) shouldIndex = this.length - 1;
  253. var $shouldActive = Z(this.$$items[shouldIndex]);
  254. $shouldActive.removeClass("z-hide").addClass("z-active").css("opacity",1);
  255. //tab 展示
  256. Z(this.$$tabs[shouldIndex]).addClass("z-active").siblings("div").removeClass("z-active");
  257. },
  258. fadeEnd: function(ev)
  259. {
  260. var $thisItem = Z(Z.E.current(ev));
  261. if (!$thisItem.hasClass("z-active")){
  262. $thisItem.addClass("z-hide").css("top",0);
  263. }
  264. },
  265. slideEnd: function(ev)
  266. {
  267. //判断是否处于 list 边缘
  268. var $activeItem = this.$ul.find(".z-active");
  269. var activeIndex = Z.AR.indexOf(this.$$items, $activeItem[0]);
  270. if (activeIndex > -1){
  271. return this.sliding = false;
  272. }
  273. $activeItem.removeClass("z-active");
  274. //无缝播放
  275. if (this.playGapless)
  276. {
  277. this.$ul.css("transition-property","none");
  278. if ($activeItem[0] === this.$firstClone[0]){
  279. this.$ul.css("transform","translate3d(0,0,0)");
  280. Z(this.$$items[0]).addClass("z-active");
  281. }
  282. if ($activeItem[0] === this.$lastClone[0]){
  283. this.$ul.css("transform","translate3d(-"+(this.length - 1) * this.width+"px,0,0)");
  284. Z(this.$$items[this.length - 1]).addClass("z-active");
  285. }
  286. }
  287. this.sliding = false;
  288. },
  289. tabTrigger: function(ev)
  290. {//tab 触发
  291. var $activeTab = this.$tab.find(".z-active");
  292. var activeIndex = Z.AR.indexOf(this.$$tabs, $activeTab[0]);
  293. var $shouldTab = Z(Z.E.current(ev));
  294. var shouldIndex = Z.AR.indexOf(this.$$tabs, $shouldTab[0]);
  295. var step = shouldIndex - activeIndex;
  296. this.sliderPlay(step);
  297. },
  298. resize: function()
  299. {
  300. // 停止自动播放
  301. this.sliding = true;
  302. if (this.playAutoTimer)
  303. {
  304. clearInterval(this.playAutoTimer);
  305. this.playAutoTimer = null;
  306. }
  307. // 设置延迟,自动播放
  308. if (!this.resizeStep)
  309. this.resizeStep = 0;
  310. this.resizeStep++;
  311. if (this.delayAutoPlay)
  312. clearTimeout(this.delayAutoPlay);
  313. this.delayAutoPlay = setTimeout(this.delayResize, this.playDuration, this, this.resizeStep);
  314. // 重置大小
  315. this.$wrap.css('width', 'auto');
  316. this.width = this.$wrap.offsetWidth();
  317. this.$wrap.css({
  318. "width": this.width,
  319. });
  320. this.$ul.css("width", this.length * this.width);
  321. this.$ul.find('li').css('width', this.width);
  322. for (var i = 0;i < this.length;i++) {
  323. Z(this.$$items[i]).css({"transform": "translate3d(" + i * this.width + "px,0,0)"});
  324. }
  325. this.$firstClone.css({"transform": "translate3d(" + this.length * this.width + "px,0,0)"});
  326. this.$lastClone.css({"transform":"translate3d(-" + this.width + "px,0,0)"});
  327. // 定位当前
  328. var $activeItem = this.$ul.find(".z-active");
  329. var activeIndex = Z.AR.indexOf(this.$$items, $activeItem[0]);
  330. var ulTrans = -activeIndex * this.width;
  331. this.$ul.css("transform", "translate3d("+ ulTrans +"px,0,0)");
  332. },
  333. delayResize: function(thisObj, resizeStep)
  334. {
  335. clearTimeout(thisObj.delayAutoPlay);
  336. if (resizeStep !== thisObj.resizeStep)
  337. return;
  338. thisObj.resizeStep = null;
  339. thisObj.autoPlay();
  340. },
  341. transitionFixed: function()
  342. {//兼容写法
  343. var $div = document.createElement('div');
  344. if ($div.style["transition"] !== undefined ){
  345. $div = null;
  346. return "transitionend";
  347. }
  348. if ($div.style["OTransition"] !== undefined ){
  349. $div = null;
  350. return "oTransitionEnd";
  351. }
  352. if ($div.style["WebkitTransition"] !== undefined ){
  353. $div = null;
  354. return "webkitTransitionEnd";
  355. }
  356. },
  357. getRectSize: function(val, all)
  358. {
  359. if (/^\d+(\.\d+)?%$/.test(val))
  360. {
  361. val = parseFloat(val) / 100 * all;
  362. }
  363. else
  364. {
  365. val = parseFloat(val) || all;
  366. if (val < 0)
  367. val = all;
  368. }
  369. return Math.round(val);
  370. },
  371. //end of Z.Zslider.prototype
  372. }
  373. //END
  374. })(zhiqim);