JS无限TAB栏切换,点击按钮自动居中

遇到一个案例,需要TAB有点击滚动的效果,并且切换显示对应的文字,
在网上搜了一圈,没发现很合适的,要不就是需要给tab和content加唯一ID(麻烦)
所以有了这个代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<base target="_blank">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
color: #dcc833;
}
li {
list-style-type: none;
}
.for9xOnly {
margin: 8px 0;
}
#top7412 {
width: 100%;
background: #f2f2f2;
white-space: nowrap;
overflow: auto;
position: relative;
scroll-behavior: smooth;
}
#top7412 li {
width: 18%;
height: 40px;
background-color: #bf9663;
display: inline-block;
text-align: center;
line-height: 40px;
margin: 3px;
transition: color 0.2s, text-shadow 0.2s;
transition-timing-function: ease-out;
color: transparent;
text-shadow:
0 0 1px rgba(254, 252, 124, 1),
0 0 3px rgba(255, 217, 54, 0.7),
0 0 5px rgba(255, 0, 0, 1),
0 0 14px rgba(255, 0, 0, 1),
0 0 17px rgba(255, 0, 0, 1),
0 0 20px rgba(255, 0, 0, 1),
0 5px 25px rgba(0, 0, 255, 0.9);
font-weight: 300;
border-radius: 5px;
}
.wobble {
animation: bounceIn .75s;
}
#top7412 li.current9888 {
background: #c0392b;
}
#bottom4651 {
width: 100%;
background: #fff;
position: relative;
}
#bottom4651 li {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
padding: 5px 15px;
display: none;
font-weight: 800;
}
#bottom4651 li p {
height: 40px;
line-height: 40px;
border-bottom: 1px solid #dcc833;
}
#bottom4651 li.current9888 {
display: block;
}
.container::-webkit-scrollbar {
display: none;
}
.container{
scrollbar-width: none;
-ms-overflow-style: none;
overflow-y: auto;
}
.result123 {
text-align: center;
height: 40px;
line-height: 40px;
margin: 5px 0;
color: red;
font-size: 20px;
background-image: linear-gradient(0deg, rgba(222, 199, 7, 0.33) 0%, rgb(255, 255, 255) 100%);
box-shadow: inset 0px 0px 0px 1px #ffffff, 0 2px 3px rgba(0, 0, 0, 0.1);
}
#bottom4651 li span {
color: #c0392b;
}
</style>
</head>
<body>
<div class="for9xOnly">
<ul id="top7412" class="container">
<li class="current9888">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<ul id="bottom4651">
<li class="current9888">
<p class="result123">我是1</p>
</li>
<li>
<p class="result123">我是2</p>
</li>
<li>
<p class="result123">我是3</p>
</li>
<li>
<p class="result123">我是4</p>
</li>
<li>
<p class="result123">我是5</p>
</li>
<li>
<p class="result123">我是6</p>
</li>
</ul>
</div>
<script>
// 获取id=top7412
var container = document.querySelector("#top7412");
// 获取id=top7412的宽
var containerW = container.offsetWidth;
// 获取id=top7412的所有li,该变量为数组
var navList = document.getElementById('top7412').getElementsByTagName('li');
// 获取id=bottom4651的所有li,该变量为数组
var contents = document.getElementById('bottom4651').getElementsByTagName('li');
// 函数名handleClick,参数event
function handleClick(event) {
// 删除 所有li的属性--class
for (var j = 0; j < navList.length; j++) {
navList[j].removeAttribute('class');
}
// 设定触发事件的元素的 class 属性的值
event.target.className = "current9888 wobble";
// 获取触发事件的元素的 index 属性的值 (即bottom4651下的li的index值)
var num = event.target.getAttribute("index");
// 遍历删除所有contents的类名(即bottom4651下的li的类名)
for (var k = 0; k < contents.length; k++) {
contents[k].removeAttribute('class');
}
// 设定触发事件的元素的 class 属性的值。总结:排他算法
contents[num].className = "current9888";
// 获取到当前点击元素的 offsetLeft - 包裹盒子 offsetWidth 的一半 + 当前点击元素 offsetWidth 的一半
// event.target.offsetLeft获取到当前点击元素的 offsetLeft(即该元素左上角到父元素左边的距离)
// containerW / 2 包裹盒子 offsetWidth 的一半
// event.target.offsetWidth / 2 当前点击元素 offsetWidth 的一半
// 这三个值相互加减,会产生什么效果?假设父盒子宽为800px,
// 此时的当前点击元素位于最右边,假设其offsetLeft为750px(显示了该盒子的一半,其他部分被隐藏),
// 其宽为100px,其一半的宽则为50px,750-400+50=300,则向左滚动300px,
var scrollLeftNum = event.target.offsetLeft - containerW / 2 + event.target.offsetWidth / 2;
// 执行container的滚动条向左滚动,如按上例,则为300px,
// 本例中使用 CSS将滚动条隐藏,形成点击元素元素自动向容器中间移动的效果
/***
CSS如下 使用overflow-y: auto;是为了可以滚动
.container::-webkit-scrollbar display: none;
.container{
scrollbar-width: none;
-ms-overflow-style: none;
overflow-y: auto;
}
*/
// container执行滚动
container.scrollLeft = scrollLeftNum;
}
// 给每个li加index,再给每个li绑定事件监听
for (var i = 0; i < navList.length; i++) {
navList[i].setAttribute("index", i);
navList[i].addEventListener('click', handleClick);
}
// 可想而知,每个top的li和对应的每个bottom的li的index值都是相同的,
// 所以不必给li们增加额外的id也可以让它们对应显示,
// 只需要在点击触发的li对应的bottom的li加一个display:block即可
/*
20241029版本更新,主要改变是:
1. 代码更合理,不再直接删除class属性,而是移除指定类名
2. 直接给class属性添加类名,不再使用覆盖式的className='类名'方法
3. 使用 scrollIntoView 代替 scrollLeft 的平滑滚动,该方法有3个可选参数:
start(元素与容器的开头对齐)
end(元素与容器的末尾对齐)
center(元素与容器的中间对齐)
用法:scrollIntoView({ behavior: 'smooth', inline: 'center' })
*/
/*
var container = document.querySelector("#top7412");
var navList = container.getElementsByTagName('li');
var contents = document.getElementById('bottom4651').getElementsByTagName('li');
function handleClick(event) {
for (var j = 0; j < navList.length; j++) {
navList[j].classList.remove('current9888', 'wobble'); // 移除指定类名
}
event.target.classList.add("current9888", "wobble"); // 添加类名
var num = event.target.getAttribute("index");
for (var k = 0; k < contents.length; k++) {
contents[k].classList.remove('current9888');
}
contents[num].classList.add("current9888");
// 使用 scrollIntoView 代替 scrollLeft 的平滑滚动
event.target.scrollIntoView({ behavior: 'smooth', inline: 'start' });
}
for (var i = 0; i < navList.length; i++) {
navList[i].setAttribute("index", i);
navList[i].addEventListener('click', handleClick);
}
*/
</script>
</body>
</html>