首先声明:这个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;
}
完整的下载链接如下: