在这篇文章中,我实现了一个基本的选项卡功能:请猛击后面的链接>> [js插件开发教程]原生js仿jquery架构扩展开发选项卡插件.还缺少两个常用的切换(自动切换与透明度渐变),当然有朋友会说,还有左右,上下等等,这些动画会放在焦点图(幻灯片)插件系列.( ...
在这篇文章中,我实现了一个基本的选项卡功能:请猛击后面的链接>> [js插件开发教程]原生js仿jquery架构扩展开发选项卡插件.
还缺少两个常用的切换(自动切换与透明度渐变),当然有朋友会说,还有左右,上下等等,这些动画会放在焦点图(幻灯片)插件系列.
(自动切换,停止控制,透明度渐变 ) 效果预览:
自动切换的实现:
这个思路很简单,开启定时器,让选项卡的索引+1,加到4的时候(选项卡的长度)从0开始
传统做法:
index = 0
index++
if ( index == 4 ) {
index = 0
}
小技巧(估计很多人都没有用过):
var i = ( index + 1 ) % 4
index为当前选中的选项卡 索引
当index = 0,他下一张就是1, 通过上面的取余操作,i = 1
当index = 3,他下一张就是0, 通过上面的取余操作,i = 0
这种方法不需要判断边界,只需要一句代码。在实际开发中,把那个4替换成选项卡的长度
好了,关键的思路和技巧有了,我们开始拼接框架了:
1 var defaults = { 2 contentClass : 'tab-content', 3 navClass : 'tab-nav', 4 activeClass : 'active', 5 triggerElements : '*', 6 activeIndex : 0, 7 evType : 'click', 8 effect : 'none', 9 auto : false,10 delay : 3000,11 duration : 100012 };
defaults参数,增加几个配置:
effect: none(没有特效) / fade( 透明度切换 )
auto: false(不会自动切换) / true ( 开启自动切换 )
delay : 多少时间 切换一个选项卡
duration: 透明度开启,这个才会用到,表示,多长时间内 完成透明度的切换
1 if ( options.effect == 'fade' ) {2 tabContent.style.position = 'relative';3 for( var i = 0; i < tabContentEle.length; i++ ) {4 tabContentEle[i].style.position = 'absolute';5 }6 tabContentEle[opt.activeIndex].style.zIndex = _contentLen + 1;7 opt.delay += opt.duration;8 }
当开启透明度变化的时候,把选项卡元素设置成定位方式,当前选中的选项卡,层级为最高!!! ( 如果不是最高层级,那么默认是最后一个选项卡在最上面,所以 “内容4” 就会在最上层,显然不是我们想要的结果)层级+定位 这一招也很常用,经常用来做显示隐藏,和透明度变化.
根据opt配置,判断是否开启了auto自动切换功能
1 //是否自动播放 2 if ( opt.auto ) { 3 for( var i = 0 ; i < tabNavEle.length; i++ ){ 4 tabNavEle[i].index = i; 5 tabNavEle[i].onmouseover = function(){ 6 _api.stop(); 7 _api.setIndex( this.index ); 8 }; 9 tabNavEle[i].onmouseout = function(){10 _api.start();11 _api.setIndex( this.index );12 };13 }14 _api.start();15 }
如果开启了,做两件事情:
1,调用start()函数,让索引+1
2,选项卡导航部分,添加事件控制 自动播放的暂停和开始
start与stop方法?
1 _api.stop = function(){ 2 timer && clearInterval( timer ); 3 }; 4 5 _api.start = function(){ 6 _api.stop(); 7 timer = setInterval( function(){ 8 _api.next(); 9 }, opt.delay );10 };
调用next方法,你应该猜得到next方法做的事情就是索引+1 吧
1 _api.next = function(){2 var i = ( _index + 1 ) % _contentLen;3 _api.setIndex( i );4 };
索引+1之后,再切换选项卡
最后在setIndex方法:增加透明度变化
1 if ( _index != index ) { 2 tabContentEle[_index].style.zIndex = _contentLen + 1; 3 for (var i = 0; i < tabContentEle.length; i++) { 4 if (i != _index) { 5 tabContentEle[i].style.zIndex = ( index + _contentLen - ( i + 1 ) ) % _contentLen + 1; 6 tabContentEle[i].style.opacity = 1; 7 } 8 } 9 animate(tabContentEle[_index], {'opacity': 0}, function () {10 tabContentEle[_index].style.zIndex = ( index + _contentLen - ( _index + 1 ) ) % _contentLen + 1;11 _index = index;12 });13 }
完整的js代码有220行:
1 /** 2 * Created by ghostwu(吴华). 3 */ 4 (function(){ 5 var G = function( selectors, context ){ 6 return new G.fn.init( selectors, context ); 7 } 8 G.fn = G.prototype = { 9 length : 0, 10 constructor : G, 11 size : function(){ 12 return this.length; 13 }, 14 init : function( selector, context ){ 15 this.length = 0; 16 context = context || document; 17 if ( selector.indexOf( '#' ) == 0 ){ 18 this[0] = document.getElementById( selector.substring( 1 ) ); 19 this.length = 1; 20 }else { 21 var aNode = context.querySelectorAll( selector ); 22 for( var i = 0, len = aNode.length; i < len; i++ ) { 23 this[i] = aNode[i]; 24 } 25 this.length = len; 26 } 27 this.selector = selector; 28 this.context = context; 29 return this; 30 } 31 } 32 33 G.fn.init.prototype = G.fn; 34 G.extend = G.fn.extend = function () { 35 var i = 1, 36 len = arguments.length, 37 dst = arguments[0], 38 j; 39 if (dst.length === undefined) { 40 dst.length = 0; 41 } 42 if (i == len) { 43 dst = this; 44 i--; 45 } 46 for (; i < len; i++) { 47 for (j in arguments[i]) { 48 dst[j] = arguments[i][j]; 49 dst.length++; 50 } 51 } 52 return dst; 53 }; 54 55 function css(obj, attr, value) { 56 if (arguments.length == 3) { 57 obj.style[attr] = value; 58 } else { 59 if (obj.currentStyle) { 60 return obj.currentStyle[attr]; 61 } else { 62 return getComputedStyle(obj, false)[attr]; 63 } 64 } 65 } 66 67 function animate(obj, attr, fn) { 68 clearInterval(obj.timer); 69 var cur = 0; 70 var target = 0; 71 var speed = 0; 72 var start = new Date().getTime();//起始时间 73 obj.timer = setInterval(function () { 74 var bFlag = true; 75 for (var key in attr) { 76 if (key == 'opacity') { 77 cur = css(obj, 'opacity') * 100; 78 } else { 79 cur = parseInt(css(obj, key)); 80 } 81 target = attr[key]; 82 speed = ( target - cur ) / 8; 83 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 84 if (cur != target) { 85 bFlag = false; 86 if (key == 'opacity') { 87 obj.style.opacity = ( cur + speed ) / 100; 88 obj.style.filter = "alpha(opacity:" + ( cur + speed ) + ")"; 89 } else { 90 obj.style[key] = cur + speed + "px"; 91 } 92 } 93 } 94 if (bFlag) { 95 var end = new Date().getTime();//结束时间 96 console.log( '总计:', ( end - start ) ); 97 clearInterval(obj.timer); 98 fn && fn.call(obj); 99 }100 }, 30 );101 }102 103 G.fn.tabs = function( options ){104 options = options || {};105 var defaults = {106 contentClass : 'tab-content',107 navClass : 'tab-nav',108 activeClass : 'active',109 triggerElements : '*',110 activeIndex : 0,111 evType : 'click',112 effect : 'none',113 auto : false,114 delay : 3000,115 duration : 1000116 };117 118 var opt = G.extend( {}, defaults, options );119 120 var tabContent = this[0].querySelector( "." + opt.contentClass );121 var tabContentEle = tabContent.children;122 var tabNavEle = this[0].querySelectorAll( "." + opt.navClass + '>' + opt.triggerElements );123 124 var _contentLen = tabContentEle.length; //选项卡个数125 var _index = opt.activeIndex;126 var timer = null;127 128 if ( options.effect == 'fade' ) {129 tabContent.style.position = 'relative';130 for( var i = 0; i < tabContentEle.length; i++ ) {131 tabContentEle[i].style.position = 'absolute';132 }133 tabContentEle[opt.activeIndex].style.zIndex = _contentLen + 1;134 opt.delay += opt.duration;135 }136 137 var _api = {};138 139 _api.next = function(){140 var i = ( _index + 1 ) % _contentLen;141 _api.setIndex( i );142 };143 144 _api.stop = function(){145 timer && clearInterval( timer );146 };147 148 _api.start = function(){149 _api.stop();150 timer = setInterval( function(){151 _api.next();152 }, opt.delay );153 };154 155 _api.setIndex = function( index ){156 //当前标签加上active样式,其余标签删除active样式157 for ( var i = 0; i < _contentLen; i++ ) {158 if ( tabNavEle[i].classList.contains( 'active' ) ) {159 tabNavEle[i].classList.remove('active');160 }161 }162 tabNavEle[index].classList.add( 'active' );163 switch ( opt.effect ){164 case 'fade':165 if ( _index != index ) {166 tabContentEle[_index].style.zIndex = _contentLen + 1;167 for (var i = 0; i < tabContentEle.length; i++) {168 if (i != _index) {169 tabContentEle[i].style.zIndex = ( index + _contentLen - ( i + 1 ) ) % _contentLen + 1;170 tabContentEle[i].style.opacity = 1;171 }172 }173 animate(tabContentEle[_index], {'opacity': 0}, function () {174 tabContentEle[_index].style.zIndex = ( index + _contentLen - ( _index + 1 ) ) % _contentLen + 1;175 _index = index;176 });177 }178 break;179 default:180 for ( var i = 0; i < _contentLen; i++ ) {181 tabContentEle[i].style.display = 'none';182 }183 tabContentEle[index].style.display = 'block';184 _index = index;185 }186 }187 188 _api.setIndex( _index ); //默认的选项卡189 190 //所有的标签绑定事件191 for( var i = 0, len = tabNavEle.length; i < len; i++ ) {192 tabNavEle[i].index = i;193 tabNavEle[i].addEventListener( opt.evType, function(){194 var i = this.index;195 _api.setIndex( i );196 }, false );197 }198 199 //是否自动播放200 if ( opt.auto ) {201 for( var i = 0 ; i < tabNavEle.length; i++ ){202 tabNavEle[i].index = i;203 tabNavEle[i].onmouseover = function(){204 _api.stop();205 _api.setIndex( this.index );206 };207 tabNavEle[i].onmouseout = function(){208 _api.start();209 _api.setIndex( this.index );210 };211 }212 _api.start();213 }214 215 return this;216 }217 218 var $ = function( selectors, context ){219 return G( selectors, context );220 }221 window.$ = $;222 })();
View Code
原标题:[js插件开发教程]实现一个比较完整的开源级选项卡插件
关键词:JS
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:
admin#shaoqun.com
(#换成@)。