如何用js写一个有滑动动画的切换table
在不久前有个H5项目上遇见一个需求需要写一个tab底部条下划线滑动效果的功能,特在此记录一下。
其实原理非常简单,底部红线和父级相对定位,改变红线的left值就能做到了。要动画效果的话底部红线的css样式加上transition
动画就可以了。下面我们上代码。
css部分
body,html{
margin: 0;
padding: 0;
}
.tab{
width: 100%;
}
.tab_top{
width: 100%;
height: 40px;
display: flex;
flex-direction: row; /* flex横向布局(从左往右) */
align-items: center; /* flex垂直居中 */
justify-content: space-around; /* flex水平平分 */
}
.tab_top .item{
font-size: 20px;
line-height: 24px;
color: #333;
}
.tab_bot{
width: 100%;
height: 4px;
position: relative;
}
.tab_bot .change_line{
width: 20px;
height: 4px;
border-radius: 2px;
background: red;
transition: all .5s; /*动画时间*/
position: absolute;
top: 0;
}
.Content1{
background: chocolate;
}
.Content2{
background: pink;
}
.Content3{
background: skyblue;
}
.changeContent{
width: 100%;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.content .none{
display: none;
}
html部分
<div class="content">
<div class="tab">
<div class="tab_top">
<div class="item">页面一</div>
<div class="item">页面二</div>
<div class="item">页面三</div>
</div>
<div class="tab_bot">
<div class="change_line"></div>
</div>
</div>
<div class="changeContent Content1">
这是页面一的内容
</div>
<div class="changeContent Content2 none">
这是页面二的内容
</div>
<div class="changeContent Content3 none">
这是页面三的内容
</div>
</div>
主要的就是下面的js部分,通过offsetWidth
和offsetWidth
获取每个选项框距父级元素左边的位置和本身的宽度,然后与红线宽度相减最后计算得到合适的left值
var tab_top=document.getElementsByClassName("tab_top")[0]
var change_line=document.getElementsByClassName("change_line")[0]
var item1=document.getElementsByClassName("item")[0]
var item2=document.getElementsByClassName("item")[1]
var item3=document.getElementsByClassName("item")[2]
var Content1=document.getElementsByClassName("Content1")[0]
var Content2=document.getElementsByClassName("Content2")[0]
var Content3=document.getElementsByClassName("Content3")[0]
let item1Left=item1.offsetLeft //分别获取各个选项距父级左边的距离
let item2Left=item2.offsetLeft
let item3Left=item3.offsetLeft
let item1Width=item1.offsetWidth //分别获取各个选项宽度
let item2Width=item2.offsetWidth
let item3Width=item3.offsetWidth
let change_lineWidth=change_line.offsetWidth //获取底部红线宽度
let item1Disparity=item1Width-change_lineWidth //分别获取各个选项宽度和底部红线宽度差距(所以红线最好小于标题宽度否则需要分别处理)
let item2Disparity=item2.offsetWidth-change_lineWidth
let item3Disparity=item3.offsetWidth-change_lineWidth
change_line.style.left=(item1Left+(item1Disparity/2))+'px' //初始时第一个被选中
item1.onclick=function(){
change_line.style.left=(item1Left+(item1Disparity/2))+'px'
Content1.classList.remove("none"); //为了防止操作给个别节点加上多余重复class,事先把所有的清掉
Content2.classList.remove("none");
Content3.classList.remove("none");
Content2.classList.add("none");
Content3.classList.add("none");
}
item2.onclick=function(){
change_line.style.left=(item2Left+(item2Disparity/2))+'px'
Content1.classList.remove("none");
Content2.classList.remove("none");
Content3.classList.remove("none");
Content1.classList.add("none");
Content3.classList.add("none");
}
item3.onclick=function(){
change_line.style.left=(item3Left+(item3Disparity/2))+'px'
Content1.classList.remove("none");
Content2.classList.remove("none");
Content3.classList.remove("none");
Content1.classList.add("none");
Content2.classList.add("none");
}
这样我们就实现tabel底部线滑动的效果了
这里有可能写得有点复杂了,如果有更好的优化方法,希望能够得到你们的指正,不积跬步,无以至千里;不善小事,何以成大器。