小程序实现左右滑动列表区域,切换菜单(横向滑动菜单,切换时自动设置选中的菜单窗口居中显示),加载显示对应瀑布流数据,页面滚动时,设置菜单栏是否置顶显示
自己写的一个demo(下载地址:https://download.csdn.net/download/qq_16494241/11208785)
app.js中加处理方法:
//处理下页列表数据,追加至列表数据存储变量中
addList(oldData, newData) {
for (var item in newData) {
oldData.push(newData[item]);
}
return oldData;
},
//处理设置最新获取到的瀑布流数据
setCurNewPubuImgData: function (oldImgDataJson) {
let oldImgData = [];
for (var item in oldImgDataJson) {
oldImgData[item] = oldImgDataJson[item];
}
return oldImgData;
},
//处理存储瀑布流左右两边数据
setCurResultsPubuImgData(newImgData, oldData, leftH, rightH ,callback) {
//let leftH = 0;
//let rightH = 0;
let resultsList = {
listL: [],
listR: [],
}
let leftStart = 0;
let rightStart = 0;
for (var item in newImgData) {
//console.log(leftH, rightH, newImgData[item].h);
//console.log(leftH <= rightH);
if (leftH <= rightH){
resultsList.listL[leftStart] = oldData[item];
leftStart ++;
leftH += newImgData[item].h;
}else{
resultsList.listR[rightStart] = oldData[item];
rightStart ++;
rightH += newImgData[item].h;
}
}
callback(resultsList , leftH, rightH);
}
index.wxml
{{item}}
{{item}}
暂无数据
{{item.title}}
{{item.nickname}}
{{item.zannum}}
{{item.key}}
{{item.title}}
{{item.nickname}}
{{item.zannum}}
{{item.key}}
我是有底线哒
index.wxss
/* pages/test/index.wxss */
@font-face {font-family: "iconfont";
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAMMAAsAAAAABygAAAK/AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCfgqCDIIMATYCJAMMCwgABCAFhG0HQxtXBhEVlBtkPxJs3OJiZX3TRZXQIr0Jolr7t2d3PwAqRrAYUECawX+ViooCQPUqGvgaIIAA7+V0DBejXqgsxfV861k+45OO+X3WeZxGKYRESIw4nDbF5wPlsuawOh8TMMGAxtoUWenExLxleK1L6aA2QwBnwiWQiqqGDhwxkF4CyMLs9CiOOT2mJVNwRLCvmWiQo9jhqPapu8CR8PHylbQcQWGnIQNbpionKLHdsd3Vu6xdDPgEBPNZAXUaaCABGJCuWnsLOo4n0DjbcUME9tVKwHbXsrDd8fm7/cMDQYHYQ9JdAYgBmbojAZdzawKYggJAA2AfJxuAbUz1HSio4ODA0auxufnX4190v2BPeFqef+54/rFjV9izZ53PagfMvfjSGRv/4lPnrtCnTztopKHpeddzfMipa2k7qw4OqzutZfVNHd2rN/za7yU6fU7Ye/E0vKOEfU5vE2/6t6/e6Oiub6JbA2fleNt+4egxrbnGfiEdEH3Ft2H+fGtHXUNz6eHDwAk5mJOf69twhREArP36vV7HvxBA4HHB2r9hj4Jvji4GgFdub34jn7Xf0N+I4805BH60oGeZcUTEoI3F53zPqUkbaVUAXM2FBXF7ez9e6dc7HQRH/FIoHAiDxpEIoqEmwA4XMmCPI8XQOotXTXfhg+zJnIA4bwTh6QPF3S1onr5EQ/3Bjr8/7Hm2h7OufBZ0EVUjygkdYwT/giZMY2ImFlHmEfOtd5QVhbQr0tqEwEhdTFU4Is0xZL1ny5wg0TRAibbDvp9gpqnFwLJmngulUt2NZJiGjVCOIIehCHgvoBFMRsmvzUTp/kcou+k51JLVZr9CZNXUDwxJ9yBW8rFX1r1cs7rLLMYSkJDJAJSoHer1JmCub9dCAZPqEdFZQdFqqa9crq8cPiBPzYN8VadEi8HlzVijI7YHndrMZgMA') format('woff2'),
url('//at.alicdn.com/t/font_1209810_s2iq0eomwkc.woff?t=1558690554699') format('woff'),
url('//at.alicdn.com/t/font_1209810_s2iq0eomwkc.ttf?t=1558690554699') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('//at.alicdn.com/t/font_1209810_s2iq0eomwkc.svg?t=1558690554699#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-xinheart280:before {
content: "\e9cb";
}
.icon-xinheart281:before {
content: "\e9cc";
}
page {
height: 100%;
font-size: 26rpx;
line-height: 1.5;
}
image{ vertical-align: middle;}
.nav_box{ width: 100%; background-color: #fff;}
.nav_box.nav_body_top{ overflow: hidden; position: fixed; left: 0; top: 0; z-index: 999;}
.nav_body{ width: auto; padding: 22rpx 0; margin: 0 auto; position: relative;
display: flex; justify-content: flex-start; align-items: center;
}
.nav_body:before{ content: ""; width: 100%; min-width: 750rpx; height: 1px; background-color: #ddd; position: absolute; left: 50%; bottom: 0;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
.nav_body:after{ content: ""; width: 124rpx; height: 1.5px; background-color: #fc2549; position: absolute; left: ; bottom: 0;
-webkit-transition:all linear .3s;
transition:all linear .3s;
}
.nav_li{ width: 150rpx; height: 52rpx; line-height: 52rpx; text-align: center; color: #000; font-size: 26rpx; position: relative;
-webkit-transition:all linear .3s;
transition:all linear .3s;
}
.nav_li:not(:first-child):after{ content: ""; width: 1px; height: 100%; background-color: #ddd; position: absolute; left: 0; top: 0;}
.nav_body.nav_body_cur0 .nav_li:nth-child(1) ,
.nav_body.nav_body_cur1 .nav_li:nth-child(2) ,
.nav_body.nav_body_cur2 .nav_li:nth-child(3) ,
.nav_body.nav_body_cur3 .nav_li:nth-child(4) ,
.nav_body.nav_body_cur4 .nav_li:nth-child(5) ,
.nav_body.nav_body_cur5 .nav_li:nth-child(6) ,
.nav_body.nav_body_cur6 .nav_li:nth-child(7) ,
.nav_body.nav_body_cur7 .nav_li:nth-child(8) ,
.nav_body.nav_body_cur8 .nav_li:nth-child(9) ,
.nav_body.nav_body_cur9 .nav_li:nth-child(10){ color: #fc2549; font-weight: bold;}
.nav_body.nav_body_cur0:after{ left: calc((150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur1:after{ left: calc(150rpx + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur2:after{ left: calc(150rpx * 2 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur3:after{ left: calc(150rpx * 3 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur4:after{ left: calc(150rpx * 4 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur5:after{ left: calc(150rpx * 5 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur6:after{ left: calc(150rpx * 6 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur7:after{ left: calc(150rpx * 7 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur8:after{ left: calc(150rpx * 8 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur9:after{ left: calc(150rpx * 9 + (150rpx - 124rpx) / 2);}
.nav_body.nav_body_cur10:after{ left: calc(150rpx * 10 + (150rpx - 124rpx) / 2);}
.showNoMore{ padding: 20rpx 0; text-align: center; color: #aaa;}
.showNoMore:before{ content: ""; display: inline-block; vertical-align: middle; width: 150rpx; height: 1px; margin: 0 15rpx; background-color: #ddd;}
.showNoMore:after{ content: ""; display: inline-block; vertical-align: middle; width: 150rpx; height: 1px; margin: 0 15rpx; background-color: #ddd;}
.body{ height: 100%; background-color: #f4f8fb;}
.swiper{ padding: 0 20rpx; background-color: #fff;}
swiper{ height: 350rpx; margin: 0 auto; overflow: hidden;}
swiper image{ width: 100%;}
/* 列表 */
.get_pubu_img{ display: none;}
.box{ margin-top: 20rpx; display: flex; flex-wrap: wrap; flex-direction: row; justify-content:flex-start; align-items: flex-start; position: relative;}
.no_data_show{ width: 100%; min-height: calc(100vh - 500rpx); margin: 0 auto; text-align: center; font-size: 36rpx; font-weight: bold; background-color: #fff; display: flex; justify-content: center; align-items: center;}
.box_l , .box_r{ width: 345rpx; margin-left: 20rpx;}
.list{ width:100%; margin-bottom: 20rpx; padding-bottom: 10rpx; border-radius: 10rpx; background-color: #fff; position: relative; overflow: hidden;
-webkit-box-shadow: 2rpx 5rpx 10rpx rgba(0,0,0,.1);
box-shadow: 2rpx 5rpx 10rpx rgba(0,0,0,.1);
}
.list > image{ width: 100%;/* border-top-left-radius: 10rpx; border-top-right-radius: 10rpx;*/}
.list_title{ height: 64rpx; line-height: 64rpx; padding: 0 20rpx; color: #4c4c4c; overflow: hidden; white-space:nowrap; text-overflow: ellipsis;}
.list_user{ height: 70rpx; padding: 0 20rpx; color: #989898;
display: flex; flex-wrap: nowrap; justify-content: flex-start; align-items: center;
}
.list_user image{ width: 50rpx; margin-right: 10rpx; border-radius: 50%;}
.list_user_name{ width: 150rpx; margin-right: 10rpx; overflow: hidden; white-space:nowrap; text-overflow: ellipsis;}
.list_zan{ display: inline-block; vertical-align: middle; width: 30rpx; height: 30rpx; margin-right: 10rpx; position: relative; top: -4rpx;}
.list_zan .iconfont{ width: 30rpx; height: 3rpx; position: absolute; left: 0; top: 0;}
index.js
// pages/test/index.js
var app = getApp()
var leftHstart = 0, rightHstart = 0; //加载下页瀑布流数据时,前面数据的左右盒子高度
var newImgData = []; //处理瀑布流所需变量
var canLoadNextPage = false;
var scrollTopH; //获取顶部高度,用于设置浮动顶部的菜单(不同尺寸手机,高度不同)
var touchLRnum = 100; //列表区域左右滑动的距离(切换菜单的值)
Page({
/**
* 页面的初始数据
*/
data: {
navList: ['首页','菜单1','菜单2','菜单3','菜单444','菜单555','菜单666','菜单777','菜单8','菜单9','菜单10'],
navIndex: 0, //当前选择的菜单key(对应 navList[key] 菜单内容)
ifShowTopNav: false, //是否显示浮动的顶部菜单
pageSize: 1, //页码
ifHaveMore: true, //是否还有下一页
moveLeft: 'left:0px;', //列表处左右滑动时位移值
ifCanScroll: true, //列表处左右滑动时设为false,这样页面不会滚动影响页面体验
//KV图相关配置
indicatordots: true,
indicatorcolor: '#989898',
indicatoractivecolor: '#fc2549',
autoplay: true,
interval: 3000,
duration: 500,
//swiperImgArr: [], //KV图数据
//列表
//pubuliuNewArrData:[], //最新一次获取到的 瀑布流JSON数据 转成 的 数组
//pubuliuResultsList:{
// listL: [],
// listR: [],
//}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let This = this;
This.getKVimg(); //获取 KV图 列表
This.initFun(); //初始化 / 清空 页面数据
This.getListData(); //获取页面列表数据
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
//获取顶部高度,用于设置浮动顶部的菜单(不同尺寸手机,高度不同)
//延迟执行是为了防止导航栏以上有些元素未加载成功会影响高度计算(最好是在导航栏以上元素请求加载成功后处执行以下代码)
setTimeout(function(){
let query = wx.createSelectorQuery();
query.select('#top').boundingClientRect()
query.exec(function (res) {
scrollTopH = res[0].height;
})
},1500);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
//初始化 / 清空 页面数据
initFun: function () {
let This = this;
leftHstart = 0, rightHstart = 0; //加载下页瀑布流数据时,前面数据的左右盒子高度
newImgData = []; //处理瀑布流所需变量
This.setData({
//swiperImgArr: '',
//navIndex: 0,
pageSize: 1, //页码
pubuliuNewArrData: '',
pubuliuResultsList: '',
});
},
//获取 KV图 列表
getKVimg: function () {
let This = this;
This.setData({
swiperImgArr: [
{ src: 'https://images.unsplash.com/photo-1551334787-21e6bd3ab135?w=640', linkUrl: '' },
{ src: 'https://images.unsplash.com/photo-1551214012-84f95e060dee?w=640', linkUrl: '' },
{ src: 'https://images.unsplash.com/photo-1551446591-142875a901a1?w=640', linkUrl: '' },
],
});
},
//设置顶部固定菜单定位
// onPageScroll:function(e){ // 获取滚动条当前位置
// console.log(e.scrollTop)
scrollIn: function (e) {
let This = this;
if (e.detail.scrollTop >= scrollTopH) {
if (!This.data.ifShowTopNav) {
This.setData({
ifShowTopNav: true
});
}
} else {
if (This.data.ifShowTopNav) {
This.setData({
ifShowTopNav: false
});
}
}
},
//左右滑动 切换菜单
touchStart: function (e) {
if (e.touches.length == 1) {
let This = this;
This.setData({
startX: e.touches[0].clientX,
startY: e.touches[0].clientY,
});
}
},
touchMove: function (e) {
if (e.touches.length == 1) {
let This = this;
let moveX = e.touches[0].clientX;
let diffX = This.data.startX - moveX;
let moveY = e.touches[0].clientY;
let diffY = This.data.startY - moveY;
let moveLeft = 'left:0px;';
if (Math.abs(diffY) < Math.abs(diffX)) {
if (diffX < 0 && This.data.navIndex > 0) { //向右
//moveLeft = 'left:' + -(diffX < touchLRnum ? -touchLRnum : diffX) + 'px;';
moveLeft = 'left:' + -diffX + 'px;';
} else if (diffX > 0 && This.data.navIndex < This.data.navList.length - 1) { //向左
//moveLeft = 'left:-' + (diffX > touchLRnum ? touchLRnum : diffX) + 'px;';
moveLeft = 'left:-' + diffX + 'px;';
}
This.setData({
ifCanScroll: false, //列表处左右滑动时设为false,这样页面不会滚动影响页面体验
});
}else{
This.setData({
ifCanScroll: true, //列表处左右滑动时设为false,这样页面不会滚动影响页面体验
});
}
This.setData({
moveLeft: moveLeft
});
}
},
touchEnd: function (e) {
if (e.changedTouches.length == 1) {
let This = this;
let endX = e.changedTouches[0].clientX;
let diffX = This.data.startX - endX;
let endY = e.changedTouches[0].clientY;
let diffY = This.data.startY - endY;
let moveLeft = 'left:0px;';
if (Math.abs(diffY) < Math.abs(diffX)) {
if (diffX < 0 && diffX < -touchLRnum && This.data.navIndex > 0) { //向右
let moveEndNavIndex = This.data.navIndex - 1;
This.setData({
navIndex: moveEndNavIndex
});
This.initFun(); //初始化 / 清空 页面数据
This.getListData(); //获取页面列表数据
} else if (diffX > 0 && diffX > touchLRnum && This.data.navIndex < This.data.navList.length - 1) { //向左
let moveEndNavIndex = This.data.navIndex + 1;
This.setData({
navIndex: moveEndNavIndex
});
This.initFun(); //初始化 / 清空 页面数据
This.getListData(); //获取页面列表数据
}
}
This.setData({
moveLeft: moveLeft,
ifCanScroll: true, //列表处左右滑动时设为false,这样页面不会滚动影响页面体验
});
}
},
//选择 切换菜单
changeTitle: function (e) {
let chooseNav = e.currentTarget.dataset.type;
let This = this;
if (chooseNav != This.data.navIndex){
This.setData({
navIndex: chooseNav,
});
This.initFun(); //初始化 / 清空 页面数据
This.getListData(); //获取页面列表数据
}
},
/**
* 页面上拉触底事件的处理函数
*/
// onReachBottom: function () {
scrollEnd: function () { //滚动到底部加载更多
let This = this;
if (This.data.ifHaveMore) {
//console.log('加载一下页');
if (!canLoadNextPage) {
return;
}
newImgData = [];
This.setData({
pubuliuNewArrData: '',
pageSize: This.data.pageSize + 1
});
This.getListData(); //获取页面列表数据
}
},
//获取页面列表数据
getListData: function () {
let This = this;
wx.showLoading({
title: '加载中',
mask:true
})
//查询数据 所需参数
let dataJson = {
type: This.data.navIndex,
page: This.data.pageSize, //页码
}
/*test*/
let res = {
status: 1,
ifHaveMore: This.data.pageSize > 2 ? false : true, //是否还有下一页
list: {
0: {
id: '001',
title: This.data.navList[This.data.navIndex] + ' - ' + This.data.pageSize + '页 - 1111111',
userhead: 'https://iconfont.alicdn.com/t/1550898018467.jpeg@100h_100w.jpg',
nickname: '昵称昵称昵称111',
zannum: 88,
ifzan: true,
src: "https://img.t.sinajs.cn/t5/skin/public/profile_cover/001_s.jpg?version=b97b8caee54a6c78",
linkUrl: '/pages/detail/detail'
},
1: {
id: '002',
title: This.data.pageSize + '页222222222222',
userhead: 'https://avatar.csdn.net/D/5/3/3_qq_16494241.jpg',
nickname: '昵称昵称昵称222',
zannum: 88,
ifzan: false,
src: "https://img2018.cnblogs.com/news/24442/201902/24442-20190214124232223-959977867.jpg",
linkUrl: '/pages/detail/detail'
},
2: {
id: '003',
title: This.data.pageSize + '页33333333333333',
userhead: 'https://avatar.csdn.net/D/5/3/3_qq_16494241.jpg',
nickname: '昵称昵称昵称333',
zannum: 88,
ifzan: false,
src: "https://s3.ifanr.com/wp-content/uploads/2018/08/211.jpg!720",
linkUrl: '/pages/detail/detail'
},
3: {
id: '004',
title: This.data.pageSize + '页44444444444444',
userhead: 'https://iconfont.alicdn.com/t/1550898018467.jpeg@100h_100w.jpg',
nickname: '昵称昵称昵称444',
zannum: 88,
ifzan: true,
src: "https://t1.hddhhn.com/uploads/tu/201512/14/87.jpg",
linkUrl: '/pages/detail/detail'
},
}
}
if (res.status == 1) {
This.setData({
ifHaveMore: res.ifHaveMore, //是否还有下一页
pubuliuNewArrData: app.setCurNewPubuImgData(res.list) //处理设置最新获取到的瀑布流数据
});
}
setTimeout(function () {
wx.hideLoading();
}, 500)
/*test*/
return;
//请求获取数据
wx.request({
url: '获取列表数据', //仅为示例,并非真实的接口地址
data: dataJson,
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
wx.hideLoading();
}
})
},
/*
瀑布流相关处理:
1、处理最新加载的瀑布流数据中图片,先显示,再根据 bindload 获取 并 存储 与 原来KEY 相对应的 等宽情况下的高度 数组
=> newImgData[key].h (key 与最新加载的JSON数据的 key 相同)
2、根据所有图片加载完成后,调用app.js中方法,设置左、右两边数据
*/
pubuImgLoad: function (e) {
let This = this;
let inListIndex = e.currentTarget.dataset.key;
//console.log(e.detail.width);
//console.log(inListIndex);
newImgData[inListIndex] = {};
newImgData[inListIndex].h = (300 / e.detail.width) * e.detail.height;
if (newImgData.length == This.data.pubuliuNewArrData.length) {
//防止最后一个数据中的图片先加载完成,这样lenth也相等
for (let i = 0; i < newImgData.length; i++) {
if (!newImgData[i]) {
return;
}
}
//newImgData 获取的最新数据 - newImgData[key].h (key 与最新加载的JSON数据的 key 相同)
//This.data.pubuliuNewArrData 获取的最新数据(处理过的数组) - This.data.pubuliuNewArrData[key]. (key 与最新加载的JSON数据的 key 相同)
//leftHstart 本次数据加载 前 的 左 边高度
//rightHstart 本次数据加载 前 的 右 边高度
app.setCurResultsPubuImgData(newImgData, This.data.pubuliuNewArrData, leftHstart, rightHstart, function (pubuliuResultsList, leftH, rightH) {
//console.log(pubuliuResultsList);
leftHstart = leftH;
rightHstart = rightH;
if (This.data.pubuliuResultsList) {
pubuliuResultsList.listL = This.data.pubuliuResultsList.listL.concat(pubuliuResultsList.listL);
pubuliuResultsList.listR = This.data.pubuliuResultsList.listR.concat(pubuliuResultsList.listR);
}
This.setData({
pubuliuResultsList: pubuliuResultsList
});
setTimeout(function () {
canLoadNextPage = true;
}, 500);
})
}
},
// 点赞、取消赞
dianzan: function (e) {
// console.log(e.currentTarget.dataset.id); //对应数据库ID 用来更新数据库中对应 赞 的
// console.log(e.currentTarget.dataset.ifzan); //当前用户是否赞过
// console.log(e.currentTarget.dataset.side); //listL(左边数据) | listR(右边数据)
// console.log(e.currentTarget.dataset.index); //对应当前页面key(左、右边) 用来更新页面上显示样式的
let This = this;
wx.showLoading({
title: '点赞中',
mask:true
})
//查询数据 所需参数
let dataJson = {
id: e.currentTarget.dataset.id, //对应数据库ID 用来更新数据库中对应 赞 的
ifzan: e.currentTarget.dataset.ifzan, //当前用户是否赞过
}
/*test*/
let res = {
status: 1,
zannum:This.data.pubuliuResultsList[e.currentTarget.dataset.side][e.currentTarget.dataset.index].zannum == 88 ? 999 : 88 , //点赞、取消赞后 的 赞数量
ifzan: !dataJson.ifzan,
info: '是否成功提示文本'
}
if (res.status == 1) {
let tempData = This.data.pubuliuResultsList;
tempData[e.currentTarget.dataset.side][e.currentTarget.dataset.index].ifzan = res.ifzan;
tempData[e.currentTarget.dataset.side][e.currentTarget.dataset.index].zannum = res.zannum;
This.setData({
pubuliuResultsList: tempData
});
} else {
}
setTimeout(function(){
wx.showToast({
title: res.info,
icon: 'success',
duration: 800
})
//wx.hideLoading();
},500)
/*test*/
return;
//请求获取数据
wx.request({
url: '获取列表数据', //仅为示例,并非真实的接口地址
data: dataJson,
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
}
})
},
})