zoukankan      html  css  js  c++  java
  • [js插件开发教程]实现一个比较完整的开源级选项卡插件

    在这篇文章中,我实现了一个基本的选项卡功能:请猛击后面的链接>>   [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 : 1000
    12         };

    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 : 1000
    116         };
    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
  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/twodog/p/12139127.html
Copyright © 2011-2022 走看看