js實現類似TabPage切換的效果
阿新 • • 發佈:2018-11-04
首先宣告:這個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; }
完整的下載連結如下: