1. 程式人生 > >js實現類似TabPage切換的效果

js實現類似TabPage切換的效果

TabPage

首先宣告:這個js演算法的原理並非原創,這裡只是學習實現的效果和原理!尊重原創,原創作者無從考證,多個開源的類似後臺管理系統中都有這個多iframe的效果,且實現的效果一致,都採用了相同的演算法版本。本人只是學習瞭解之後,做了一個精簡版的還原。

首先核心的js實現程式碼如下:

$(function () {
    top.vpms = top.vpms || {};
    vpms.tabPage = (function () {

        var newTabIndex = 0;
        var scrollTabLeft = function () {
            var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
            var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".page-tabs"));
            var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
            var scrollVal = 0;
            if ($(".page-tabs-content").width() < visibleWidth) {
                return false;
            } else {
                var tabElement = $(".tab-page:first");
                var offsetVal = 0;
                while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) {
                    offsetVal += $(tabElement).outerWidth(true);
                    tabElement = $(tabElement).next();
                }
                offsetVal = 0;
                if (calSumWidth($(tabElement).prevAll()) > visibleWidth) {
                    while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {
                        offsetVal += $(tabElement).outerWidth(true);
                        tabElement = $(tabElement).prev();
                    }
                    scrollVal = calSumWidth($(tabElement).prevAll());
                }
            }
            $('.page-tabs-content').animate({
                marginLeft: 0 - scrollVal + 'px'
            }, "fast");
        };
        var scrollTabRight = function () {
            var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left')));
            var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".page-tabs"));
            var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
            var scrollVal = 0;
            if ($(".page-tabs-content").width() < visibleWidth) {
                return false;
            } else {
                var tabElement = $(".tab-page:first");
                var offsetVal = 0;
                while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) {
                    offsetVal += $(tabElement).outerWidth(true);
                    tabElement = $(tabElement).next();
                }
                offsetVal = 0;
                while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) {
                    offsetVal += $(tabElement).outerWidth(true);
                    tabElement = $(tabElement).next();
                }
                scrollVal = calSumWidth($(tabElement).prevAll());
                if (scrollVal > 0) {
                    $('.page-tabs-content').animate({
                        marginLeft: 0 - scrollVal + 'px'
                    }, "fast");
                }
            }
        };

        var scrollToTab = function (element) {
            var marginLeftVal = calSumWidth($(element).prevAll());
            var marginRightVal = calSumWidth($(element).nextAll());
            var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".page-tabs"));
            var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth;
            var scrollVal = 0;
            if ($(".page-tabs-content").outerWidth() < visibleWidth) {
                scrollVal = 0;
            } else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) {  //marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))
                if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) {
                    scrollVal = marginLeftVal;
                    var tabElement = element;
                    while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content").outerWidth() - visibleWidth)) {
                        scrollVal -= $(tabElement).prev().outerWidth();
                        tabElement = $(tabElement).prev();
                    }
                }
                //alert(scrollVal);   
            } else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) {   //- $(element).prev().outerWidth(true)
                scrollVal = marginLeftVal - $(element).prev().outerWidth(true);
            }
            $('.page-tabs-content').animate({
                marginLeft: 0 - scrollVal + 'px'
            }, "fast");
            activeTab(element);
        };

     

        var calSumWidth = function (element) {
            var width = 0;
            $(element).each(function () {
                width += $(this).outerWidth(true);
            });
            return width;
        };

        var activeTab = function (a) {
            var currentId = $(a).data('id');
            if (!$(a).hasClass('active')) {
                $(a).addClass('active').siblings('.tab-page').removeClass('active');
                scrollToTab(a);
            }
        };


        var closeTab = function () {
            var currentWidth = $(this).parents('.tab-page').width();
            //如果當前已經啟用
            if ($(this).parents('.tab-page').hasClass('active')) {
                if ($(this).parents('.tab-page').next('.tab-page').length>0) {
                    $(this).parents('.tab-page').next('.tab-page:eq(0)').addClass('active');
                    
                    var marginLeftVal = parseInt($('.page-tabs-content').css('margin-left'));
                    if (marginLeftVal < 0) {
                        $('.page-tabs-content').animate({
                            marginLeft: (marginLeftVal + currentWidth) + 'px'
                        }, "fast");
                    }
                    $(this).parents('.tab-page').remove();
                }
                if ($(this).parents('.tab-page').prev('.tab-page').length>0) {
                    $(this).parents('.tab-page').prev('.tab-page:last').addClass('active');
                    
                    $(this).parents('.tab-page').remove();
                   
                }
                //scrollToTab($('.tab-page.active'));
            }
            else {
                $(this).parents('.tab-page').remove();
                scrollToTab($('.tab-page.active'));
            }
            return false;
        };

        var addTab = function () {
            $('.tab-page').removeClass('active');
            newTabIndex++;
            $(".page-tabs-content").append('<a href="javascript:;" class="tab-page active" data-id="">新增的選項卡' + newTabIndex+'<i class="fa fa-times-circle"></i></a>');
            scrollToTab($('.tab-page.active'));
        };

        var init = function (tabCount) {
            for (var i = 0; i < tabCount; i++) {
                $(".selectALinkHook").append("<option>" + (i + 1) + "</option>");
                $(".page-tabs-content").append('<a href="javascript:;" class="tab-page" data-id="">選項卡'+(i+1)+'<i class="fa fa-times-circle"></i></a>');
            }
            $(".page-tabs-content>a:first").addClass("active");
            $('.selectALinkHook').on('change', function () {
                var tabIndex = Number($(".selectALinkHook option:selected").val());
                var ele = $(".page-tabs-content").find("a").get(tabIndex - 1);
                if (ele)
                    scrollToTab(ele);
            });
            $('.tabLeft').on('click', vpms.tabPage.scrollTabLeft);
            $('.tabRight').on('click', vpms.tabPage.scrollTabRight);
            $('.page-tabs-content .tab-page').on('click', function () {
                activeTab(this);
            });
            //$('.page-tabs-content').on('click', '.tab-page',function () {
            //    activeTab(this);
            //});
            $('.page-tabs-content .tab-page i').on('click', vpms.tabPage.closeTab);
            $("#btnAddTab").click(function () {
                addTab();
            });
        };

        return {
            init: init,
            scrollTabLeft: scrollTabLeft,
            scrollTabRight: scrollTabRight,
            addTab: addTab,
            activeTab: activeTab,
            closeTab: closeTab,
            calSumWidth: calSumWidth
        };
    })();
    vpms.tabPage.init(50);
});

HTML結構如下:

    <div style="margin:50px 50px">
        <div style="margin-bottom:30px;">
            <label>轉到第:</label>
            <select style="width:100px; font-size:large;" class="selectALinkHook"></select>

            <button id="btnAddTab">新增頁</button>
        </div>
        <div class="content-tabs">
            <button class="nav-button roll-nav roll-left tabLeft">
                <i class="fa fa-backward"></i>
            </button>
            <nav class="page-tabs">
                <div class="page-tabs-content">
                    <!--<a href="javascript:;" class="tab-page" data-id="">選項卡1<i class="fa fa-times-circle"></i></a>-->
                </div>

            </nav>
            <button class="nav-button roll-nav roll-right tabRight">
                <i class="fa fa-forward"></i>
            </button>
        </div>
    </div>

 

css部分如下:

body {
    margin:0;
    padding:0;
    overflow-x:hidden;
}

.content-tabs {
    position:relative;
    display:inline-block;
    height: 41px;
    width: 60%;
    margin:0px;
    padding:0px;
    border-bottom: solid 2px #2c3e50;
    background:#fff !important;
    border-top: none;
    text-align:left;
    overflow-x:hidden;
    z-index:100;
}

.content-tabs nav.page-tabs {
    margin-left: 40px;
    width: 100000px;
    height: 40px;
    overflow: hidden;
}

.content-tabs .roll-nav {
    position: absolute;
    width: 40px;
    height: 39px;
    text-align: center;
    color: #475059;
    z-index: 2;
    top: 0;
}

 .content-tabs .nav-button {
        background: #fff;
        border: 0;
        height: 40px;
        width: 40px;
        outline: none;
    }

.content-tabs .roll-left {
    border:none;
    color:#999;
    border-right: solid 1px #eee;
}

.content-tabs .roll-left:hover,
.content-tabs .roll-right:hover{
    color: #475059;
}

.content-tabs .roll-right {
    border: none;
    color:#999;
    border-left: solid 1px #eee;
}

.content-tabs nav.page-tabs .page-tabs-content {
    float: left;
}

.content-tabs .page-tabs a {
    display: inline-block;
    height:40px;
    line-height:40px;
    float: left;
    border-right: solid 1px #eee;
    padding: 0 15px;
    text-decoration: none;
    color: #999;
    display: block;
    z-index:0;
}
.content-tabs .page-tabs a:hover {
    background-color:#f3f3f4;
    color:#475059;
}

.content-tabs .page-tabs a.active {
    background: #2f4050;
    color: #a7b1c2;
}

.content-tabs .page-tabs a.active:hover {
    color: #fff;
}
    
.content-tabs .page-tabs a > i {
    margin-left: 5px;
}


.content-tabs .roll-right.tabRight {
    right: 0;
}

完整的下載連結如下:

https://download.csdn.net/download/elie_yang/10680350