實現(xiàn)右邊內(nèi)容滑動,左邊側(cè)欄聯(lián)動被選中
效果
小程序滑動效果.gif
實現(xiàn)方式
- wsml
<view class="container">
<view class='content'>
<view class="box">
<view class="left">
<scroll-view scroll-y="true" style="height:{{scrollHeight}}px;" scroll-top="{{scrollTopLeft}}">
<view wx:for="{{list}}" data-index="{{index}}" bindtap="toScrollView">
<view class="left-item {{selectedSub==index?'left-active':''}}">側(cè)欄{{index+1}}</view>
</view>
</scroll-view>
</view>
<view class="right">
<scroll-view scroll-y="true" style="height:{{scrollHeight}}px;" scroll-into-view="{{toView}}" scroll-top="0" bindscroll="scrollTo" scroll-with-animation>
<view wx:for="{{list}}" id="position{{index}}">
<view class="right-item">
<view class="right-classify-title">分類名稱{{index+1}}</view>
<view wx:for="{{item.list}}">
<view class="flex" style="height:80px;width:100%;">
<image src="/assets/images/recharge.jpg" style="width:100rpx;height:100rpx;"></image>
<view>內(nèi)容{{index+1}}</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</view>
// pages/purchase/index.js
let scrollDdirection = 0; // 用來計算滾動的方向
Page({
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
selectedSub: 0, // 選中的分類
scrollHeight: 0, // 滾動視圖的高度
list: Array.from(Array(8), (item, index) => {
return {
title: "分類",
list: Array.from(Array(10))
}
}),
toView: 'position0' // 滾動視圖跳轉(zhuǎn)的位置
scrollTopLeft: 0, // 左邊滾動位置隨著右邊分類而滾動
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
onLoad: function(options) {
// 獲取設(shè)備信息
wx.getSystemInfo({
success: res => {
this.setData({
scrollHeight: res.windowHeight
})
}
})
// 獲取數(shù)據(jù)
this.getData();
},
// 獲取數(shù)據(jù)
getData(){
setTimeout(() => {
// 異步請求數(shù)據(jù),請求完畢并且渲染數(shù)據(jù)之后才可以執(zhí)行l(wèi)isenerScroll
this.setData({
// list:requestData // 得到請求的數(shù)據(jù),并且渲染視圖
},() => {
// 獲取所有分類的頭部偏移量
this.lisenerScroll();
})
},300)
},
/**
* 跳轉(zhuǎn)滾動條位置
*/
toScrollView(e) {
const {
selectedSub
} = this.data
const {
index
} = e.currentTarget.dataset
let left_ = 0
if (index > 3) {
left_ = (index - 3) * 50 // 左邊側(cè)欄item高度為50,可以根據(jù)自己的item高度設(shè)置
}
this.setData({
selectedSub: index,
toView: `position${index}`,
scrollTopLeft: left_
})
},
/**
* 獲取右邊每個分類的頭部偏移量
*/
lisenerScroll() {
// 獲取各分類容器距離頂部的距離
new Promise(resolve => {
let query = wx.createSelectorQuery();
for (let i in this.data.list) {
query.select(`#position${i}`).boundingClientRect();
}
query.exec(function(res) {
resolve(res);
});
}).then(res => {
this.data.list.forEach((item, index) => {
item.offsetTop = res[index].top
})
this.setData({
scrollInfo: res,
list: this.data.list
})
});
},
/**
* 監(jiān)聽滾動條滾動事件
*/
scrollTo(e) {
const scrollTop = e.detail.scrollTop; //滾動的Y軸
const {
selectedSub,
list
} = this.data;
let left_ = 0
if (scrollDdirection < scrollTop) {
// 向上滑動
scrollDdirection = scrollTop
// 計算偏移位置
if (selectedSub < list.length - 1 && scrollTop >= list[selectedSub + 1].offsetTop) {
if (selectedSub > 2) {
left_ = (selectedSub - 2) * 50
}
this.setData({
selectedSub: selectedSub + 1,
scrollTopLeft: left_
})
}
} else {
// 向下滑動
scrollDdirection = scrollTop
// 計算偏移位置
if (selectedSub > 0 && scrollTop < list[selectedSub].offsetTop && scrollTop > 0) {
if (selectedSub > 3) {
left_ = (selectedSub - 4) * 50
}
this.setData({
selectedSub: selectedSub - 1,
scrollTopLeft: left_
})
}
}
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面初次渲染完成
*/
onReady: function() {
},
})
- wxss
/* pages/purchase/index.wxss */
.box {
display: flex;
}
.left {
width: 25vw;
}
.left-item {
padding: 30rpx 20rpx;
background-color: #eee;
}
.left-active {
background-color: #fff;
border-left: 6rpx solid red;
}
.right {
width: 75vw;
background: #fff;
padding: 0 20rpx;
}
.right-classify-title {
font-size: 0.9rem;
color: #777;
height: 50px;
line-height: 60px;
}