美文网首页一步步完成一个前端框架
东拼西凑完成一个“前端框架”(5) - Tabs操作

东拼西凑完成一个“前端框架”(5) - Tabs操作

作者: OldsixShang | 来源:发表于2020-01-06 23:48 被阅读0次

    目录

    写在前面

    Tabs页面完成的基本操作完成,但是功能还不够完备:

    • Tab页打开过多超出的如何处理?
    • Tab页关闭所有、关闭其它操作
    • Tab页刷新操作

    设计

    这里参考LayUIAdmin的设计方式:

    1. Tab栏左右未知可以动态调整
    2. 打开的标签页面超出时,调整位置到指定标签页显示
    3. 左右滑动不同范围的标签页


      image.png

    布局

    • Tab栏左右位置可以调整,那么Tab栏的定位是绝对定位
    • 左右调整动画 transaction

    代码

    HTML

    ···
     <div class="ls-tab-container">
        <div class="header flex">
            <!--left-->
            <div class="tab-operate tab-operate-left">
                <a class="fa fa-2x fa-angle-double-left opt-left"></a>
            </div>
            <!--titles-->
            <div class="ls-tab-titles flex">
                <div class="tab-title active" data-id="0">
                    <span class="title">
                        <i class="ls-icon ls-icon-home"></i>
                    </span>
                </div>
            </div>
            <!--right-->
            <div class="tab-operate tab-operate-right">
                <a class="fa fa-2x fa-angle-double-right opt-right"></a>
                <a class="fa fa-2x fa-angle-double-down">
                    <div class="dropdown-panel">
                        <ul>
                            <li class="opt" data-opt="refresh">刷新</li>
                            <li class="opt" data-opt="closeOthers">关闭其它</li>
                            <li class="opt" data-opt="closeAll">全部关闭</li>
                        </ul>
                    </div>
                </a>
            </div>
        </div>
    ···
    </div>
    ···
    

    CSS

    <!--Tabs栏-->
    .ls-tab-container .ls-tab-titles {
        position: absolute;
        left: 39px;
        right: 78px;
        overflow: hidden;
        transition: all 300ms ease-in;
        -webkit-transition: all 300ms ease-in;
    }
    <!--操作-->
    
    .tab-operate {
        position: absolute;
        display: flex;
        text-align: center;
        border-bottom: 1px solid #e6e6e6;
        background: rgba(255, 255, 255, 1);
        box-shadow: 0 0 6px rgba(196, 199, 202, 0.35);
        z-index: 8;
    }
    
    .tab-operate .fa:hover {
        background: rgba(238, 238, 238, .6);
        cursor: pointer;
    }
    
    .tab-operate.tab-operate-left {
        left: 0;
    }
    
    .tab-operate.tab-operate-right {
        right: 0;
    }
    
    .tab-operate .fa {
        color: #666;
        font-size: 22px;
        line-height: 36px;
        width: 38px;
        display: inline-block;
    }
    
    .tab-operate-left .fa {
        border-right: 1px solid rgb(230, 230, 230, .8);
    }
    
    .tab-operate-right .fa {
        border-left: 1px solid rgb(230, 230, 230, .8);
        position: relative;
    }
    

    效果

    image.png

    下拉菜单

    鼠标经过最右侧操作按钮时展示下拉菜单,思路很简单就算用伪类 hover 实现,但是在利用transaction做动画的过程中发现,display 属性与 transaction 属性冲突,解决方式是通过 height:0;overflow:hidden; 来实现动画:

    .dropdown-panel {
        background: #fff;
        position: absolute;
        width: 120px;
        right: 0;
        font-size: 13px;
        transition: top 200ms ease-in, opacity 200ms ease-in;
        -webkit-transition: top 200ms ease-in, opacity 200ms ease-in;
        border-radius: 4px;
        top: 46px;
        height: 0;
        opacity: 0;
        overflow: hidden;
        box-shadow: 0 0 6px rgba(196, 199, 202, .35);
    }
    
    .tab-operate-right .fa:hover .dropdown-panel {
        top: 37px;
        opacity: 1;
        height: auto;
        border: 1px solid rgb(230, 230, 230, .8);
    }
    

    效果预览

    4.gif

    操作

    思路

    image.png
    如图所示 打开多个标签页时只要把超出的部分利用 Tab栏margin-left 属性补回来就可以实现:
    margin-left: (Tab栏.Offset().Left+Tabs栏.Width() - TabItem.Offset().Left-TabItem.Width()) + 'px'

    关键代码实现

    // 激活Tab时触发
    ···
    // 位置调整
    var pleft = $tab.offset().left + 39;
    var pright = $tab.offset().left + $tab.width() - 80;
    var cleft = $tabTitle.offset().left;
    var cright = cleft + $tabTitle.width() + 30;
    var cmgLeft = parseFloat($tabTitle.parent().css("margin-left").replace("px", ""));
    
    if (cleft < pleft) {
        cmgLeft = (cmgLeft + pleft - cleft);
        $tabTitle.parent().css("margin-left", cmgLeft + "px");
    } else if (cright > pright) {
        cmgLeft = (cmgLeft + pright - cright);
        $tabTitle.parent().css("margin-left", cmgLeft + "px");
    }
    ···
    

    左右滑动

    思路

    分页的思想:把Tabs栏的宽度类比为 PageSize[分页大小] , 打开标签页占用的总长度类比为 TotalCount[总数]

    关键代码实现

    
    /**
     * 翻页
     * @param {页码}} pageIndex 
     */
    var changePage = function(diff) {
        // 容器宽度
        var cWidth = $('.ls-tab-container').width() - 119;
        var $firstTitle = $('.ls-tab-titles .tab-title:first'),
            $lastTitle = $('.ls-tab-titles .tab-title:last');
        // 内容宽度
        var tsWidth = $lastTitle.offset().left -
            $firstTitle.offset().left +
            $lastTitle.width() + 30;
        var curPage = $title_container.attr("cur-p");
    
        // 容器 margin-left 用于计算当前页码
        var cmgLeft = parseFloat($title_container.css("margin-left").replace("px", ""));
        curPage = Math.floor(Math.abs(cmgLeft) / cWidth) + 1;
    
        var totalPage = Math.floor(tsWidth / cWidth) + (tsWidth % cWidth > 0 ? 1 : 0);
        curPage = curPage + diff;
        if (curPage >= totalPage) {
            curPage = totalPage;
            $title_container
                .css("margin-left", (1 - totalPage) * cWidth + "px")
                .attr("cur-p", totalPage);
        } else if (curPage <= 1) {
            curPage = 1;
            $title_container
                .css("margin-left", "0px")
                .attr("cur-p", "1");
        } else {
            $title_container
                .css("margin-left", (1 - curPage) * cWidth + "px")
                .attr("cur-p", curPage);
        }
    }
    

    效果预览

    5.gif

    欢迎批评指正

    源码地址

    https://github.com/LaosanShang/ls-admin-frontend

    相关文章

      网友评论

        本文标题:东拼西凑完成一个“前端框架”(5) - Tabs操作

        本文链接:https://www.haomeiwen.com/subject/gwelactx.html