最近开发移动端,遇到了一个滑动导航子模块点击自动居中的需求。通过几小时的努力,多种尝试后,实现了以下效果:
前两个模块点击时不会居中,之后每个模块,在点击后,自动去居中。 开始想法是使用css transform 去移动当前的盒子进行偏移,但出现一个问题,在移动到居中位置后,去滑动滚动条,因为偏移的原因,导致显示不全。 尝试去设置当前盒子滚动位置后,完美解决当前问题。 由于使用Vue框架,绑定事件后,不进行传参,通过target方法拿到当前点击的dom节点。 以下是代码:
html:
<div class="horizontal">
<div :class="checkId == index ? ' child active':'child'"
v-for="(item,index) in navList"
v-bind:key="item.id"
:data-id="item.id"
:data-index="index"
@click="horizontalChange">
{{item.name}}
</div>
</div>
js方法:
horizontalChange (val) {
this.checkId = val.target.getAttribute('data-index')
// 获取当前点击的子元素
let child = val.target
// 获取当前视口的宽度
let windowWidth = window.innerWidth
// 获取视口减去子元素本身宽度后一半的值
let diffWidth = (windowWidth - child.getBoundingClientRect().width) / 2
// 获取当前需要移动的距离,计算方式是用当前元素距离父元素左侧的距离减去视口居中数值
let targetOffset = child.offsetLeft - diffWidth;
// 如果得到的值是负数,则表示当前子元素不需要滚动
if (targetOffset < 0) {
document.querySelector('.horizontal').scrollLeft = 0;
return
}
// 设置当前需要滚动的盒子的滚动条位置
document.querySelector('.horizontal').scrollLeft = targetOffset
// parent.style.transform = 'translateX(-' + targetOffset / 100 + 'rem)';
},
css样式:
.horizontal {
overflow-x: auto;
margin: 0.3rem;
transition: scroll linear 0.5s;
scroll-behavior: smooth;
display: flex;
.child {
flex-shrink: 0;
padding: 0.1rem 0.2rem;
color: #333;
margin-right: 0.4rem;
background: #f6f6f6;
font-size: 0.28rem;
border-radius: 0.3rem;
}
.child:last-child {
margin-right: 0;
}
.child.active {
color: #fff;
background: #eb6100;
}
}
由于使用原生js方法,所以同样适用于pc端,灵活使用即可。