TouchSlide.1.1.source.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*!
  2. * TouchSlide v1.1
  3. * javascript触屏滑动特效插件,移动端滑动特效,触屏焦点图,触屏Tab切换,触屏多图切换等
  4. * 详尽信息请看官网:http://www.SuperSlide2.com/TouchSlide/
  5. *
  6. * Copyright 2013 大话主席
  7. *
  8. * 请尊重原创,保留头部版权
  9. * 在保留版权的前提下可应用于个人或商业用途
  10. * 1.1 宽度自适应(修复安卓横屏时滑动范围不变的bug)
  11. */
  12. var TouchSlide = function(a){
  13. a = a||{};
  14. var opts = {
  15. slideCell:a.slideCell || "#touchSlide", //运行效果主对象,必须用id!,例如 slideCell:"#touchSlide"
  16. titCell:a.titCell || ".hd li", // 导航对象,当自动分页设为true时为“导航对象包裹层”
  17. mainCell:a.mainCell || ".bd", // 切换对象包裹层
  18. effect:a.effect || "left", // 效果,支持 left、leftLoop
  19. autoPlay:a.autoPlay || false, // 自动播放
  20. delayTime:a.delayTime || 200, // 效果持续时间
  21. interTime:a.interTime ||2500, // 自动运行间隔
  22. defaultIndex:a.defaultIndex ||0, // 默认的当前位置索引。0是第一个; defaultIndex:1 时,相当于从第2个开始执行
  23. titOnClassName:a.titOnClassName ||"on", // 当前导航对象添加的className
  24. autoPage:a.autoPage || false, // 自动分页,当为true时titCell为“导航对象包裹层”
  25. prevCell:a.prevCell ||".prev", // 前一页按钮
  26. nextCell:a.nextCell ||".next", // 后一页按钮
  27. pageStateCell:a.pageStateCell ||".pageState", // 分页状态对象,用于显示分页状态,例如:2/3
  28. pnLoop:a.pnLoop=='undefined '?true:a.pnLoop , // 前后按钮点击是否继续执行效果,当为最前/后页是会自动添加“prevStop”/“nextStop”控制样色
  29. startFun:a.startFun || null, // 每次切换效果开始时执行函数,用于处理特殊情况或创建更多效果。用法 satrtFun:function(i,c){ }; 其中i为当前分页,c为总页数
  30. endFun:a.endFun || null, // 每次切换效果结束时执行函数,用于处理特殊情况或创建更多效果。用法 endFun:function(i,c){ }; 其中i为当前分页,c为总页数
  31. switchLoad:a.switchLoad || null //每次切换效果结束时执行函数,用于处理特殊情况或创建更多效果。用法 endFun:function(i,c){ }; 其中i为当前分页,c为总页数
  32. }
  33. var slideCell = document.getElementById(opts.slideCell.replace("#",""));
  34. if( !slideCell ) return false;
  35. //简单模拟jquery选择器
  36. var obj = function(str,parEle){
  37. str = str.split(" ");
  38. var par = [];
  39. parEle = parEle||document;
  40. var retn = [ parEle ] ;
  41. for( var i in str ){ if(str[i].length!=0) par.push(str[i]) } //去掉重复空格
  42. for( var i in par ){
  43. if( retn.length==0 ) return false;
  44. var _retn = [];
  45. for ( var r in retn )
  46. {
  47. if( par[i][0] =="#" ) _retn.push( document.getElementById( par[i].replace("#","") ) );
  48. else if( par[i][0] =="." ){
  49. var tag = retn[r].getElementsByTagName('*');
  50. for( var j=0; j<tag.length; j++ ){
  51. var cln = tag[j].className;
  52. if( cln && cln.search(new RegExp("\\b" + par[i].replace(".","") + "\\b"))!=-1 ){ _retn.push( tag[j] ); }
  53. }
  54. }
  55. else { var tag = retn[r].getElementsByTagName( par[i] ); for( var j=0; j<tag.length; j++ ){ _retn.push( tag[j] ) } }
  56. }
  57. retn =_retn;
  58. }
  59. return retn.length==0 || retn[0] == parEle ? false:retn;
  60. }// obj E
  61. // 创建包裹层
  62. var wrap = function(el, v){
  63. var tmp = document.createElement('div');
  64. tmp.innerHTML = v;
  65. tmp = tmp.children[0];
  66. var _el = el.cloneNode(true);
  67. tmp.appendChild(_el);
  68. el.parentNode.replaceChild(tmp, el);
  69. conBox = _el; // 重置conBox
  70. return tmp;
  71. };
  72. // 获取样色数值
  73. var getStyleVal =function(el, attr){ var v=0; if(el.currentStyle){ v= el.currentStyle[attr] } else { v= getComputedStyle(el,false)[attr]; } return parseInt(v.replace("px","")) }
  74. // class处理
  75. var addClass =function(ele, className){
  76. if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) return;
  77. ele.className += (ele.className ? " " : "") + className;
  78. }
  79. var removeClass = function(ele, className){
  80. if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) return;
  81. ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
  82. }
  83. //全局对象
  84. var effect = opts.effect;
  85. var prevBtn = obj( opts.prevCell,slideCell )[0];
  86. var nextBtn = obj( opts.nextCell,slideCell )[0];
  87. var pageState = obj( opts.pageStateCell )[0];
  88. var conBox = obj( opts.mainCell,slideCell )[0];//内容元素父层对象
  89. if( !conBox ) return false;
  90. var conBoxSize= conBox.children.length;
  91. var navObj = obj( opts.titCell,slideCell );//导航子元素结合
  92. var navObjSize = navObj?navObj.length:conBoxSize;
  93. var sLoad=opts.switchLoad;
  94. /*字符串转换*/
  95. var index=parseInt(opts.defaultIndex);
  96. var delayTime=parseInt(opts.delayTime);
  97. var interTime=parseInt(opts.interTime);
  98. var autoPlay = (opts.autoPlay=="false"||opts.autoPlay==false)?false:true;
  99. var autoPage = (opts.autoPage=="false"||opts.autoPage==false)?false:true;
  100. var loop = (opts.pnLoop=="false"||opts.pnLoop==false)?false:true;
  101. var oldIndex = index;
  102. var inter=null;// autoPlay的setInterval
  103. var timeout = null; // leftLoop的setTimeout
  104. var endTimeout = null; //translate的setTimeout
  105. var startX = 0;
  106. var startY = 0;
  107. var distX = 0;
  108. var distY = 0;
  109. var dist = 0; //手指滑动距离
  110. var isTouchPad = (/hp-tablet/gi).test(navigator.appVersion);
  111. var hasTouch = 'ontouchstart' in window && !isTouchPad;
  112. var touchStart = hasTouch ? 'touchstart' : 'mousedown';
  113. //var touchMove = hasTouch ? 'touchmove' : 'mousemove';
  114. var touchMove = hasTouch ? 'touchmove' : '';
  115. var touchEnd = hasTouch ? 'touchend' : 'mouseup';
  116. var slideH=0;
  117. var slideW= conBox.parentNode.clientWidth;// mainCell滑动距离
  118. var twCell;
  119. var scrollY ;
  120. var tempSize = conBoxSize;
  121. //处理分页
  122. if( navObjSize==0 )navObjSize=conBoxSize;
  123. if( autoPage ){
  124. navObjSize=conBoxSize;
  125. navObj=navObj[0];
  126. navObj.innerHTML="";
  127. var str="";
  128. if( opts.autoPage==true|| opts.autoPage=="true" ){ for( var i=0; i<navObjSize; i++ ){ str+="<li>"+(i+1)+"</li>" } }
  129. else{ for( var i=0; i<navObjSize; i++ ){ str+=opts.autoPage.replace("$",(i+1)) } }
  130. navObj.innerHTML=str;
  131. navObj = navObj.children;//重置navObj
  132. }
  133. if( effect == "leftLoop" ){
  134. tempSize +=2;
  135. conBox.appendChild( conBox.children[0].cloneNode(true) );
  136. conBox.insertBefore( conBox.children[conBoxSize-1].cloneNode(true),conBox.children[0] );
  137. }
  138. twCell = wrap(conBox,'<div class="tempWrap" style="overflow:hidden; position:relative;"></div>');
  139. conBox.style.cssText="width:"+tempSize*slideW+"px;"+"position:relative;overflow:hidden;padding:0;margin:0;";
  140. for ( var i =0; i<tempSize; i++ ){ conBox.children[i].style.cssText="display:table-cell;vertical-align:top;width:"+slideW+"px" }
  141. var doStartFun=function(){ if ( typeof opts.startFun =='function' ){ opts.startFun( index,navObjSize ) } }
  142. var doEndFun=function(){ if ( typeof opts.endFun =='function' ){ opts.endFun( index,navObjSize ) } }
  143. var doSwitchLoad=function( moving ){
  144. var curIndex = ( effect=="leftLoop"?index+1:index ) + moving;
  145. var changeImg = function( ind ){
  146. var img = conBox.children[ind].getElementsByTagName("img");
  147. for ( var i=0; i<img.length ; i++ )
  148. {
  149. if ( img[i].getAttribute(sLoad) ){
  150. img[i].setAttribute("src", img[i].getAttribute(sLoad) );
  151. img[i].removeAttribute( sLoad );
  152. }
  153. }
  154. }// changeImg E
  155. changeImg( curIndex );
  156. if( effect=="leftLoop" ){
  157. switch ( curIndex )
  158. {
  159. case 0: changeImg( conBoxSize );break;
  160. case 1: changeImg( conBoxSize+1 );break;
  161. case conBoxSize: changeImg( 0 );break;
  162. case conBoxSize+1: changeImg( 1 );break;
  163. }
  164. }
  165. }// doSwitchLoad E
  166. //动态设置滑动宽度
  167. var orientationChange = function(){
  168. slideW = twCell.clientWidth;
  169. conBox.style.width = tempSize*slideW +"px";
  170. for ( var i =0; i<tempSize; i++ ){ conBox.children[i].style.width=slideW+"px"; }
  171. var ind = effect == "leftLoop"? index+1:index;
  172. translate( -ind*slideW ,0 );
  173. }
  174. window.addEventListener("resize", orientationChange, false);
  175. //滑动效果
  176. var translate = function( dist, speed, ele ) {
  177. if( !!ele ){ ele=ele.style; }else{ ele=conBox.style; }
  178. ele.webkitTransitionDuration = ele.MozTransitionDuration = ele.msTransitionDuration = ele.OTransitionDuration = ele.transitionDuration = speed + 'ms';
  179. ele.webkitTransform = 'translate(' + dist + 'px,0)' + 'translateZ(0)';
  180. ele.msTransform = ele.MozTransform = ele.OTransform = 'translateX(' + dist + 'px)';
  181. }
  182. //效果函数
  183. var doPlay=function(isTouch){
  184. switch (effect)
  185. {
  186. case "left":
  187. if ( index >= navObjSize) { index = isTouch?index-1:0; } else if( index < 0) { index = isTouch?0:navObjSize-1; }
  188. if( sLoad!=null ){ doSwitchLoad(0) }
  189. translate( (-index*slideW),delayTime ); oldIndex=index; break;
  190. case "leftLoop":
  191. if( sLoad!=null ){ doSwitchLoad(0) }
  192. translate( -(index+1)*slideW ,delayTime );
  193. if ( index==-1){
  194. timeout= setTimeout( function(){ translate( -navObjSize*slideW ,0 ); }, delayTime );
  195. index = navObjSize-1;
  196. }
  197. else if( index==navObjSize ){ timeout= setTimeout( function(){ translate( -slideW ,0 ); }, delayTime );
  198. index = 0;
  199. }
  200. oldIndex=index;
  201. break;// leftLoop end
  202. }//switch end
  203. doStartFun();
  204. endTimeout= setTimeout( function(){ doEndFun() }, delayTime );
  205. //设置className
  206. for ( var i=0; i<navObjSize; i++ )
  207. {
  208. removeClass(navObj[i],opts.titOnClassName);
  209. if( i == index ){ addClass(navObj[i],opts.titOnClassName) }
  210. }
  211. if( loop==false ){ //loop控制是否继续循环
  212. removeClass( nextBtn,"nextStop" );removeClass( prevBtn,"prevStop" );
  213. if (index==0 ){ addClass( prevBtn,"prevStop" ) }
  214. else if (index==navObjSize-1 ){ addClass( nextBtn,"nextStop" ) }
  215. }
  216. if(pageState){ pageState.innerHTML= "<span>"+(index+1)+"</span>/"+navObjSize; }
  217. };// doPlay end
  218. //初始化执行
  219. doPlay();
  220. //自动播放
  221. if (autoPlay) {
  222. inter=setInterval(function(){ index++; doPlay() }, interTime);
  223. }
  224. //点击事件
  225. if( navObj ){
  226. for ( var i=0; i<navObjSize; i++ )
  227. {
  228. (function(){
  229. var j = i;
  230. navObj[j].addEventListener('click', function(e){ clearTimeout( timeout ); clearTimeout( endTimeout ); index=j; doPlay(); })
  231. })()
  232. }
  233. }
  234. if(nextBtn){ nextBtn.addEventListener('click', function(e){ if ( loop==true || index!=navObjSize-1 ){ clearTimeout( timeout ); clearTimeout( endTimeout ); index++; doPlay(); } }) }
  235. if(prevBtn){ prevBtn.addEventListener('click', function(e){ if ( loop==true || index!=0 ){ clearTimeout( timeout ); clearTimeout( endTimeout ); index--; doPlay(); } }) }
  236. //触摸开始函数
  237. var tStart = function(e){
  238. clearTimeout( timeout );clearTimeout( endTimeout );
  239. scrollY = undefined;
  240. distX = 0;
  241. var point = hasTouch ? e.touches[0] : e;
  242. startX = point.pageX;
  243. startY = point.pageY;
  244. //添加“触摸移动”事件监听
  245. conBox. addEventListener(touchMove, tMove,false);
  246. //添加“触摸结束”事件监听
  247. conBox.addEventListener(touchEnd, tEnd ,false);
  248. }
  249. //触摸移动函数
  250. var tMove = function(e){
  251. if( hasTouch ){ if ( e.touches.length > 1 || e.scale && e.scale !== 1) return }; //多点或缩放
  252. var point = hasTouch ? e.touches[0] : e;
  253. distX = point.pageX-startX;
  254. distY = point.pageY-startY;
  255. if ( typeof scrollY == 'undefined') { scrollY = !!( scrollY || Math.abs(distX) < Math.abs(distY) ); }
  256. if( !scrollY ){
  257. e.preventDefault(); if(autoPlay){clearInterval(inter) }
  258. switch (effect){
  259. case "left":
  260. if( (index==0 && distX>0) || (index>=navObjSize-1&&distX<0 )){ distX=distX*0.4 }
  261. translate( -index*slideW+distX ,0 );
  262. break;
  263. case "leftLoop":translate( -(index+1)*slideW+distX ,0 );break;
  264. }
  265. if( sLoad!=null && Math.abs(distX)>slideW/3 ){
  266. doSwitchLoad( distX>-0?-1:1 )
  267. }
  268. }
  269. }
  270. //触摸结束函数
  271. var tEnd = function(e){
  272. if(distX==0) return;
  273. e.preventDefault();
  274. if( !scrollY )
  275. {
  276. if( Math.abs(distX) > slideW/10 ){ distX>0? index--: index++; }
  277. doPlay( true );
  278. if (autoPlay) {
  279. inter=setInterval(function(){ index++; doPlay() }, interTime);
  280. }
  281. }
  282. conBox.removeEventListener(touchMove, tMove, false);
  283. conBox.removeEventListener(touchEnd, tEnd, false);
  284. }
  285. //添加“触摸开始”事件监听
  286. conBox.addEventListener(touchStart, tStart ,false);
  287. }// TouchSlide E