微信小程序scroll-view滑动点击跟随导航:
<view class="demo">
<view class="nav-list">
<scroll-view scroll-x="{{true}}" scroll-with-animation="true" class="nav-scroll-view" scroll-left="{{scrollLeft}}" show-scrollbar="{{false}}">
<view class="row">
<view class="nav-item {{index == viewNavIndex && 'active'}}" wx:for="{{10}}" wx:key="index" bindtap="handleClickNav" data-nav="{{index}}">
列表{{index + 1}}
</view>
</view>
</scroll-view>
</view>
<view class="list-wrapper">
<scroll-view class="list-container" id="list-container" bindscroll="handleListScroll" bind:touchstart="handleTouchScrollView" scroll-x="{{true}}" scroll-into-view="scroll-item-{{clickedNavIndex}}" show-scrollbar="{{false}}" scroll-with-animation="{{true}}">
<view class="content">
<view class="list" wx:for="{{10}}" wx:key="index" id="scroll-item-{{index}}" style="background-color:{{colorString[index]}}">
<text class="list-item">{{item}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
function debounce(fn, interval) {
let timer;
let delay = interval || 500;
return function () {
let that = this;
let args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn.apply(that, args);
}, delay);
};
}
Page({
data: {
isTouchScrollView: false,
clickedNavIndex: 0,
viewNavIndex: 0,
nodeInfoList: [],
leftDistance: 0,
scrollLeft: 0,
contentScrollW: 0,
nodeNavList: [],
colorString: [],
},
onLoad(options) {
this.getData();
},
getData() {
var { row, colorString } = this.data;
var ColorCharacter = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
];
for (var i = 0; i < 10; i++) {
var HomeNumber = "#";
for (var j = 0; j < 6; j++) {
var NumberRand = Math.floor(Math.random() * 16);
HomeNumber += ColorCharacter[NumberRand];
}
colorString.push(HomeNumber);
}
console.log(colorString);
this.setData({
colorString,
});
},
initNode() {
const that = this;
const query = wx.createSelectorQuery().in(this);
query
.select(".nav-scroll-view")
.boundingClientRect((data) => {
console.log(data);
this.data.contentScrollW = data.width;
})
.exec();
query
.selectAll(".nav-item")
.boundingClientRect((data) => {
console.log(data);
that.setData({
nodeNavList: data,
});
})
.exec();
query
.selectAll("#list-container .list")
.boundingClientRect((data) => {
console.log(data);
that.setData({
nodeInfoList: data,
});
})
.exec();
},
handleClickNav(e) {
const that = this;
const { nav } = e.currentTarget.dataset;
console.log(nav);
const { isTouchScrollView, clickedNavIndex } = this.data;
if (!isTouchScrollView && clickedNavIndex == nav) return;
this.data.isTouchScrollView = false;
if (clickedNavIndex == nav) {
return;
this.setData({
clickedNavIndex: -1,
});
}
wx.nextTick(() => {
that.setData({
clickedNavIndex: nav,
viewNavIndex: nav,
scrollLeft: that.getScrollLeft(nav),
});
});
},
handleListScroll(e) {
const { isTouchScrollView, nodeInfoList, leftDistance } = this.data;
if (!isTouchScrollView) return;
this.scrollLeft = e.detail.scrollLeft;
let currentNavIndex = nodeInfoList
.map((item, index) => ({ index, ...item }))
.filter((item) => item.left <= this.scrollLeft + leftDistance)
.sort((a, b) => b.left - a.left)[0].index;
this.setData({
viewNavIndex: currentNavIndex,
scrollLeft: this.getScrollLeft(currentNavIndex),
});
},
getScrollLeft(index) {
const { nodeNavList, contentScrollW } = this.data;
const scrollLeft =
nodeNavList[index].left -
contentScrollW / 2 +
nodeNavList[index].width / 2;
return scrollLeft;
},
handleTouchScrollView() {
this.data.isTouchScrollView = true;
},
onReady() {
this.initNode();
},
});
.demo {
.nav-list {
display: flex;
position: sticky;
top: 0;
left: 0;
z-index: 9;
width: 100%;
background-color: #fff;
.row {
display: flex;
}
.nav-item {
padding: 25rpx 15rpx;
font-size: 28rpx;
text-align: center;
white-space: nowrap;
transition: transform 0.1s linear;
&.active {
color: #fb7d34;
transform-origin: center center;
transform: scale(1.1);
}
&:active {
background-color: rgba(0, 0, 0, 0.1);
}
}
}
.list-wrapper {
width: 100%;
position: relative;
.list-container {
display: flex;
width: 100%;
.content {
display: flex;
}
.list {
flex: 0 0 750rpx;
height: 300rpx;
}
}
}
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
}
![效果图](https://img-blog.csdnimg.cn/c113bf4e53744ebdac9f341adad872d3.jpeg#pic_center)