微信小程序scroll-view實現(xiàn)左右聯(lián)動
本文實例為大家分享了微信小程序scroll-view實現(xiàn)左右聯(lián)動的具體代碼,供大家參考,具體內(nèi)容如下
需求:項目中做了一個選擇城市的需求,要求全國所有的省市區(qū)都按照中文首字母分類并排序,左側(cè)的城市列表和右側(cè)的字母列表實現(xiàn)雙向聯(lián)動。

第一步:根據(jù)騰訊提供的javascript SDK提供的接口,獲取所有的省市區(qū),并將省市區(qū)按照首字母進行分類排序。
let _this = this;
_this.mapCtx = wx.createMapContext("myMap");
// 實例化API核心類
qqmapsdk = new QQMapWX({
key: MAP_KEY,
});
// 獲取全國的城市列表
qqmapsdk.getCityList({
success: function (res) {
let list = res.result[0].concat(res.result[1], res.result[2]);
_this.allCity = list;
_this.cityList = _this.pySegSort(list);
},
fail: function (error) {
console.error(error);
},
complete: function (res) {
console.log(res);
},
});
pySegSort(arr) {
if (!String.prototype.localeCompare) return null;
let letters = "*ABCDEFGHJKLMNOPQRSTWXYZ".split("");
let zh = "阿八嚓噠妸發(fā)旮哈譏咔垃痳拏噢妑七呥扨它穵夕丫帀".split("");
let segs = [];
let curr;
letters.forEach(function (item, i) {
curr = { letter: item, id: item, data: [] };
arr.forEach(function (item2) {
if (
(!zh[i - 1] || zh[i - 1].localeCompare(item2.fullname) <= 0) &&
item2.fullname.localeCompare(zh[i]) == -1
) {
curr.data.push(item2);
}
});
if (curr.data.length) {
curr.data.sort(function (a, b) {
return a.fullname.localeCompare(b.fullname);
});
segs.push(curr);
}
});
return segs;
},
第二步: 計算各個首字母組成的列表的高度
在使用query.selectAll('.cityList')時應(yīng)放入setTimeout中異步獲取,不然頁面還沒加載完,獲取不到,嘗試使用$nextTick()也是沒有獲取到的。
// 獲取熱門城市盒子的高度
let query = wx.createSelectorQuery().in(this);
query
.select(".hot-city")
.boundingClientRect((data) => {
this.hotCityHeight = data.height;
})
.exec();
// 獲取各個字母分類的塊高度
setTimeout(() => {
let query = wx.createSelectorQuery().in(this);
query
.selectAll(".cityList")
.boundingClientRect((data) => {
console.log(data, "各個城市分類的高度");
this.letterBoxHeight = data;
this.heightArr = this.getHeiht();
})
.exec();
}, 1000); // 使用setTimeout進行異步獲取,不然獲取不到
// 計算每個區(qū)域的高度
getHeiht() {
let n = this.hotCityHeight;
let arr = [];
this.letterBoxHeight.forEach((item) => {
n = n + item.height;
arr.push(n);
});
return arr;
},
第三步:實現(xiàn)點擊右側(cè),左側(cè)聯(lián)動。
點擊右側(cè)字母列表時,實現(xiàn)左側(cè)城市列表的滾動到可視區(qū)域,這時需要 scroll-into-view="childViewId"
// 點擊右側(cè)的字母
letterClick(letter, i) {
this.letterIndex = i;
this.currentIndex = i;
this.childViewId = letter;
setTimeout(() => {
this.letterIndex = -1;
}, 500); // 0.5秒后浮出的首字母圓圈消失
},
第四步:實現(xiàn)滑動左側(cè),右側(cè)聯(lián)動。
當滑動城市列表時,需要判斷當前的滾動高度,在哪個字母范圍內(nèi),在該范圍內(nèi)的字母需高亮。
calculateIndex(arr, scrollHeight) {
let index = "";
for (let i = 0; i < arr.length; i++) {
if (scrollHeight >= this.hotCityHeight && scrollHeight < arr[0]) {
index = 0;
} else if (scrollHeight >= arr[i - 1] && scrollHeight < arr[i]) {
index = i;
}
}
return index;
},
// 計算滾動距離
scroll(e) {
let scrollTop = e.detail.scrollTop;
let scrollArr = this.heightArr;
let index = this.calculateIndex(scrollArr, scrollTop);
this.currentIndex = index;
},
完成代碼如下:
created() {
let _this = this;
_this.mapCtx = wx.createMapContext("myMap");
// 實例化API核心類
qqmapsdk = new QQMapWX({
key: MAP_KEY,
});
// 獲取全國的城市列表
qqmapsdk.getCityList({
success: function (res) {
let list = res.result[0].concat(res.result[1], res.result[2]);
_this.allCity = list;
_this.cityList = _this.pySegSort(list);
},
fail: function (error) {
console.error(error);
},
complete: function (res) {
console.log(res);
},
});
},
mounted() {
// 獲取熱門城市盒子的高度
let query = wx.createSelectorQuery().in(this);
query
.select(".hot-city")
.boundingClientRect((data) => {
this.hotCityHeight = data.height;
})
.exec();
// 獲取各個字母分類的塊高度
setTimeout(() => {
let query = wx.createSelectorQuery().in(this);
query
.selectAll(".cityList")
.boundingClientRect((data) => {
console.log(data, "各個城市分類的高度");
this.letterBoxHeight = data;
this.heightArr = this.getHeiht();
})
.exec();
}, 1000);
},
methods: {
// 給城市列表根據(jù)首字母排序
pySegSort(arr) {
if (!String.prototype.localeCompare) return null;
let letters = "*ABCDEFGHJKLMNOPQRSTWXYZ".split("");
let zh = "阿八嚓噠妸發(fā)旮哈譏咔垃痳拏噢妑七呥扨它穵夕丫帀".split("");
let segs = [];
let curr;
letters.forEach(function (item, i) {
curr = { letter: item, id: item, data: [] };
arr.forEach(function (item2) {
if (
(!zh[i - 1] || zh[i - 1].localeCompare(item2.fullname) <= 0) &&
item2.fullname.localeCompare(zh[i]) == -1
) {
curr.data.push(item2);
}
});
if (curr.data.length) {
curr.data.sort(function (a, b) {
return a.fullname.localeCompare(b.fullname);
});
segs.push(curr);
}
});
return segs;
},
// 點擊右側(cè)的字母
letterClick(letter, i) {
this.letterIndex = i;
this.currentIndex = i;
this.childViewId = letter;
setTimeout(() => {
this.letterIndex = -1;
}, 500);
},
// 計算每個區(qū)域的高度
getHeiht() {
let n = this.hotCityHeight;
let arr = [];
this.letterBoxHeight.forEach((item) => {
n = n + item.height;
arr.push(n);
});
return arr;
},
calculateIndex(arr, scrollHeight) {
let index = "";
for (let i = 0; i < arr.length; i++) {
if (scrollHeight >= this.hotCityHeight && scrollHeight < arr[0]) {
index = 0;
} else if (scrollHeight >= arr[i - 1] && scrollHeight < arr[i]) {
index = i;
}
}
return index;
},
// 計算滾動距離
scroll(e) {
let scrollTop = e.detail.scrollTop;
let scrollArr = this.heightArr;
let index = this.calculateIndex(scrollArr, scrollTop);
this.currentIndex = index;
},
}
<scroll-view scroll-y style="height: 1400rpx" :scroll-into-view="childViewId" @scroll="scroll">
<!-- 熱門城市 -->
<view class="hot-city">
<p>熱門城市</p>
<ul>
<li
v-for="(item, idx) in hotCityList"
:key="idx"
:class="fixedPosition === item ? 'selected' : ''"
@click="selectCity(item)"
>
{{ item }}
</li>
</ul>
</view>
<!-- 字母列表 -->
<view class="letterAz">
<view
v-for="(item, idx) in letterAz"
:key="idx"
class="letter-item"
:class="currentIndex === idx ? 'selected' : ''"
@click="letterClick(item, idx)"
>
{{ item }}
<view v-show="letterIndex === idx" class="pop-item">{{ item }}</view>
</view>
</view>
<!-- 城市列表 -->
<view v-for="(item, idx) in cityList" :key="idx" class="cityList">
<view :id="item.id" class="city-letter">{{ item.letter }}</view>
<view v-for="ele in item.data" :key="ele.id" class="city-name" @click="selectCity(ele.fullname)">{{
ele.fullname
}}</view>
</view>
</scroll-view>
// 熱門城市
.hot-city {
padding: 38rpx 32rpx;
p {
font-size: 28rpx;
line-height: 40rpx;
color: #999999;
margin-bottom: 32rpx;
}
ul {
display: flex;
flex-wrap: wrap;
& li {
background: rgba(0, 0, 0, 0.04);
border-radius: 16rpx;
font-size: 28rpx;
color: #000000;
text-align: center;
margin: 8rpx;
padding: 16rpx 46rpx;
}
& li.selected {
background: rgba(45, 200, 77, 0.12);
border: 0.66rpx solid #046a38;
color: #046a38;
}
}
}
// 字母列表
.letterAz {
position: fixed;
right: 29rpx;
top: 380rpx;
font-size: 20rpx;
line-height: 28rpx;
color: rgba(0, 0, 0, 0.55);
.letter-item {
position: relative;
margin-top: 4rpx;
.pop-item {
position: absolute;
right: 165%;
bottom: -100%;
width: 96rpx;
height: 96rpx;
background: #ffffff;
border: 0.66rpx solid rgba(0, 0, 0, 0.12);
box-sizing: border-box;
box-shadow: 0 10rpx 24rpx rgba(0, 0, 0, 0.08);
border-radius: 100%;
text-align: center;
line-height: 96rpx;
font-size: 40rpx;
color: rgba(0, 0, 0, 0.85);
}
}
.letter-item.selected {
color: #046a38;
}
}
// 城市列表
.cityList {
margin-left: 32rpx;
margin-right: 66rpx;
margin-top: 20rpx;
.city-letter {
font-size: 28rpx;
line-height: 40rpx;
color: #999999;
}
.city-name {
font-size: 28rpx;
line-height: 40rpx;
color: #000000;
padding: 32rpx 0;
border-bottom: 2rpx solid rgba(0, 0, 0, 0.12);
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Javascript 完美運動框架(逐行分析代碼,讓你輕松了運動的原理)
這篇文章主要介紹了Javascript 完美運動框架,逐行分析代碼,讓你輕松了運動的原理,需要的朋友可以參考下2015-01-01
JavaScript+Canvas實現(xiàn)繪制音頻可視化波形圖
這篇文章主要為大家詳細介紹了如何利用JavaScript和Canvas實現(xiàn)繪制音頻可視化波形圖,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習一下2024-02-02
小程序?qū)崿F(xiàn)搜索界面 小程序?qū)崿F(xiàn)推薦搜索列表效果
這篇文章主要為大家詳細介紹了小程序?qū)崿F(xiàn)搜索界面,小程序?qū)崿F(xiàn)推薦搜索列表效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-05-05
JavaScript在圖片繪制文字兩種方法的實現(xiàn)與對比
這篇文章主要為大家詳細介紹了前端實現(xiàn)在圖片上繪制文字的兩種思路,支持即粘即貼即用,文中的示例代碼講解詳細,需要的小伙伴可以了解下2024-03-03

