zoukankan      html  css  js  c++  java
  • vue 插件tab选项卡(转载)

    <template>
        <tab :options="tabOpt" :state.sync="stateIndex"></tab>
    </template>
    <script type="text/babel">
        import tab from 'components/tab_touch';
        export default {
            data(){
                tabOpt:undefined,
                stateIndex:0
            },
            components:{
            "tab":tab
            },
            ready(){
                this.tabOpt={
                    count: 2.3,
                    pin:true,
                    htmls:[
                        "<span>白日登山</span>",
                        "<span>望烽火</span>",
                        "<span>黄昏饮马</span>",
                        "<span>傍交河</span>",
                        "<span>行人刁斗</span>",
                        "<span>风沙暗</span>",
                        "<span>公主琵琶</span>",
                        "<span>幽怨多</span>",
                        "<span>野营万里</span>",
                        "<span>无城郭</span>",
                        "<span>雨雪纷纷</span>",
                        "<span>连大漠</span>"
                    ],
                    slideCallback:function (dex) {
                        console.log(dex);
                    },
                    tabClassName:"tab",
                    tabActiveClassName: "active"
                }
            }
        }
    </script>

    options参数释义

    参数名简称是否必填类型含义默认值其它
    count 展示tab数 必填项 数值|一屏中露出tab的个数| 无      
    pin 是否固定到顶部 可选项 布尔 当垂直滚动时,该组件即将超出屏幕时是否固定到头部 false  
    htmls tab内容 必填项 数组[字符串] 在tab中显示的html  
    tabClassName tabClassName 可选项 字符串 单个tab的class名 一般用于自定义样式
    tabActiveClassName tabActiveClassName 可选项 字符串

    激活的tab的class名

    <template>
        <div class="fixWrap">
            <div class="component-tabsWrap" :id="tabsWrapID"
                 v-touch:pan="onPan">
                <div class="component-tabs" :style="wrapStyle">
                    <div class="component-tab" v-for="item in options.htmls" track-by="$index" :style="''+tWidth+'px'"
                         @click.stop="this.state=$index"
                         :class="[options.tabClassName,$index==state?options.tabActiveClassName:'']">
                        {{{item}}}
                    </div>
                </div>
            </div>
        </div>
    </template>
    <style lang="sass" rel="stylesheet/sass">
        @import "tab.sass"
    </style>
    <script lang="babel" type="text/babel">
        var VueTouch = require ('vue-touch');
        Vue.use (VueTouch);
        import requestAnimFrame  from "utils/requestAnimFrame"
        const sign = (num)=> {
            return num >= 0 ? 1 : -1
        }
        export default {
            props: ["options", "state"],
            data(){
                return {
                    tabsWrapID: undefined,//外容器ID
                    wrapWidth: "", //外容器宽度
                    tWidth: 0, //每一个选项卡应该有多宽
                     0, //宽度。
                    startTransX: 0,
                    transX: 0, //元素样式偏移。
                    cssX: 0 //动作中css实际完成的偏移。
                }
            },
            methods: {
                init(){
                    this.wrapWidth = document.getElementById (this.tabsWrapID).offsetWidth;
                    this.tWidth = this.wrapWidth / this.options.count;
                    this.width = this.tWidth * this.options.htmls.length;
                    setTimeout(function(){
                        this.$el.style["height"]= this.$el.children[0].clientHeight+"px";
                    }.bind(this),0)
                    if (this.options.pin) {
                        var elemRect = this.$el.getBoundingClientRect ();
                        var windowOffset = this.getWindowOffset ();
                        var winOffsetY = windowOffset.offsetY;
                        this.elemOffsetY = elemRect.top + winOffsetY;
                        document.addEventListener ('scroll', this.isTop);
                    }
                },
                onPan(event){
                    if (this.options.disPan) return;
                    this.transX = event.deltaX + this.startTransX;
                    this.cssX = this.transX;
                    if (event.eventType == 4) {
                        this.transX = -Math.round (-this.transX / this.tWidth) * this.tWidth; //整格滑动
                        var start = null;
                        if (this.transX > 0) {
                            // 头部回弹
                            this.transX = 0;
                            var speed = 24;
                            requestAnimFrame (step.bind (this));
                            function step (timestamp) {
                                this.cssX -= speed;
                                if (this.cssX > this.transX) requestAnimFrame (step.bind (this));
                                else this.startTransX = this.cssX = this.transX;
                            };
                        }
                        else if (this.transX < this.wrapWidth - this.width) {
                            // 尾部回弹
                            this.transX = this.wrapWidth - this.width;
                            var speed = 24;
                            requestAnimFrame (step.bind (this));
                            function step (timestamp) {
                                this.cssX += speed;
                                if (this.cssX < this.transX) requestAnimFrame (step.bind (this));
                                else this.startTransX = this.cssX = this.transX;
                            };
                        }
                        else {
                            //整格落位
                            let speed = 6;
                            let _sign = sign (this.cssX - this.transX);
                            if (_sign * (this.cssX - this.transX) > 1) requestAnimFrame (step.bind (this));
                            else this.cssX = this.transX;
                            function step (timestamp) {
                                if (start === null) start = timestamp;
                                let progress = timestamp - start;
                                if (progress < 3000) speed *= 1 - progress / 3000;
                                this.cssX -= _sign * speed;
                                if (_sign * (this.cssX - this.transX) > 1) requestAnimFrame (step.bind (this));
                                else this.cssX = this.transX;
                            };
                        }
                        this.startTransX = this.transX; //滑动结束设置下次滑动起始值。
                    }
    
                },
                slideTo(dex){
                    this.state = dex;
                    let speed = 10;
                    // 开头几个
                    if (dex + 1 <= this.options.count) {
                        this.transX = 0; // 设置应到位置。
                        if (this.startTransX < this.transX) {
                            let _sign = sign (this.transX - this.startTransX);
                            this.cssX = this.transX - _sign * this.tWidth;
                            requestAnimFrame (step.bind (this));
                            function step () {
                                this.cssX += _sign * speed;
                                if (_sign * (this.cssX - this.transX) < 0) requestAnimFrame (step.bind (this));
                                else {
                                    this.cssX = this.startTransX = this.transX;
                                    if (this.options.slideCallback) this.options.slideCallback (dex);
                                }
                                ;
                            };
                        }
                        //无需动画
                        else {
                            this.cssX = this.startTransX = this.transX;
                            if (this.options.slideCallback) this.options.slideCallback (dex);
                        }
                    }
                    // 结尾几个
                    else if (this.options.htmls.length - dex <= this.options.count) {
                        this.transX = this.wrapWidth - this.width;// 设置应到位置。
                        if (this.startTransX > this.transX) {
                            let _sign = sign (this.transX - this.startTransX);
                            this.cssX = this.transX - _sign * this.tWidth;
                            requestAnimFrame (step.bind (this));
                            function step () {
                                this.cssX += _sign * speed;
                                if (_sign * (this.cssX - this.transX) < 0) requestAnimFrame (step.bind (this));
                                else {
                                    this.cssX = this.startTransX = this.transX;
                                    if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                                }
    
                            };
                        }
                        else {
                            this.cssX = this.startTransX = this.transX; //无需动画
                            if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                        }
                    }
                    //
                    else {
                        this.transX = -this.tWidth * dex;// 设置应到位置。
                        let _sign = sign (this.transX - this.startTransX);
                        if (this.tWidth * (dex + 0.5 * (1 - _sign)) + this.startTransX >= 0 && this.tWidth * (dex + 0.5 * (1 - _sign)) + this.startTransX <= this.wrapWidth) {
                            //无需动画
                            this.cssX = this.transX = this.startTransX;
                            if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                        }
                        else {
                            //需要动画
                            this.cssX = this.transX - _sign * this.tWidth;
                            requestAnimFrame (step.bind (this));
                            function step () {
                                this.cssX += _sign * speed;
                                if (_sign * (this.cssX - this.transX) < 0) requestAnimFrame (step.bind (this));
                                else {
                                    this.cssX = this.startTransX = this.transX;
                                    if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                                }
                            };
                        }
                    }
                },
                isTop(){
                    var windowOffset = this.getWindowOffset (),
                            winOffsetY = windowOffset.offsetY,
                            isTop;
                    isTop = this.elemOffsetY <= winOffsetY;
                    if (isTop) {
                        this.$el.children[0].style['position'] = 'fixed';
                        this.$el.children[0].style['top'] = '0';
                        this.$el.children[0].style['left'] = '0';
                    }
                    else {
                        this.$el.children[0].style['position']='relative';
                    }
                    return isTop;
                },
                getWindowOffset(){
                    var t;
                    var win = window;
                    var pageXOffset = (typeof win.pageXOffset == 'number') ? win.pageXOffset : (((t = doc.documentElement) || (t = body.parentNode)) && typeof t.ScrollLeft == 'number' ? t : body).ScrollLeft;
                    var pageYOffset = (typeof win.pageYOffset == 'number') ? win.pageYOffset : (((t = doc.documentElement) || (t = body.parentNode)) && typeof t.ScrollTop == 'number' ? t : body).ScrollTop;
                    return {
                        offsetX: pageXOffset,
                        offsetY: pageYOffset
                    };
                },
            },
            watch: {
                options(){
                    this.tabsWrapID = parseInt (Math.random () * 1e10);
                    setTimeout (this.init.bind (this), 10);
                },
                state(val){
                    this.slideTo(val)
                }
            },
            computed: {
                wrapStyle(){
                    var _str = "";
                    if (this.width) _str += `${this.width}px;`;//宽度
                    _str += `-webkit-transform:translateX(${this.cssX}px);` //位移。
                    _str += `transform:translateX(${this.cssX}px);` //位移。
                    return _str
                }
            }
        }
    </script>
    <style lang="sass" rel="stylesheet/sass" type="sass">
    .fixWrap
      z-index: 999
      position: relative
    .component-tabsWrap
       100%
      overflow: hidden
      min-height: .1rem
      position: relative
      background: #fff
      .component-tabs
        height: 100%
        display: table
        .component-tab
          display: table-cell
          box-sizing: border-box
          text-align: center
          vertical-align: middle
    </style>

    来源:http://blog.csdn.net/keliyxyz/article/details/52208484

  • 相关阅读:
    leetCode 87.Scramble String (拼凑字符串) 解题思路和方法
    《代码阅读》读书笔记(一)
    用VMware 8安装Ubuntu 12.04具体过程(图解)
    模板方法
    POJ 2528 Mayor&#39;s posters 离散化+线段树
    <Linux> Xen虚拟机镜像的安装
    Android中的动画详解系列【2】——飞舞的蝴蝶
    jQuery:多个AJAX/JSON请求对应单个回调
    Android中的动画详解系列【1】——逐帧动画
    Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动
  • 原文地址:https://www.cnblogs.com/xiaozhumaopao/p/7852816.html
Copyright © 2011-2022 走看看