微信小程序scroll-view實(shí)現(xiàn)左右聯(lián)動(dòng)
本文實(shí)例為大家分享了微信小程序scroll-view實(shí)現(xiàn)左右聯(lián)動(dòng)的具體代碼,供大家參考,具體內(nèi)容如下
需求:項(xiàng)目中做了一個(gè)選擇城市的需求,要求全國(guó)所有的省市區(qū)都按照中文首字母分類并排序,左側(cè)的城市列表和右側(cè)的字母列表實(shí)現(xiàn)雙向聯(lián)動(dòng)。
第一步:根據(jù)騰訊提供的javascript SDK提供的接口,獲取所有的省市區(qū),并將省市區(qū)按照首字母進(jìn)行分類排序。
let _this = this; _this.mapCtx = wx.createMapContext("myMap"); // 實(shí)例化API核心類 qqmapsdk = new QQMapWX({ key: MAP_KEY, }); // 獲取全國(guó)的城市列表 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; },
第二步: 計(jì)算各個(gè)首字母組成的列表的高度
在使用query.selectAll('.cityList')時(shí)應(yīng)放入setTimeout中異步獲取,不然頁面還沒加載完,獲取不到,嘗試使用$nextTick()也是沒有獲取到的。
// 獲取熱門城市盒子的高度 let query = wx.createSelectorQuery().in(this); query .select(".hot-city") .boundingClientRect((data) => { this.hotCityHeight = data.height; }) .exec(); // 獲取各個(gè)字母分類的塊高度 setTimeout(() => { let query = wx.createSelectorQuery().in(this); query .selectAll(".cityList") .boundingClientRect((data) => { console.log(data, "各個(gè)城市分類的高度"); this.letterBoxHeight = data; this.heightArr = this.getHeiht(); }) .exec(); }, 1000); // 使用setTimeout進(jìn)行異步獲取,不然獲取不到 // 計(jì)算每個(gè)區(qū)域的高度 getHeiht() { let n = this.hotCityHeight; let arr = []; this.letterBoxHeight.forEach((item) => { n = n + item.height; arr.push(n); }); return arr; },
第三步:實(shí)現(xiàn)點(diǎn)擊右側(cè),左側(cè)聯(lián)動(dòng)。
點(diǎn)擊右側(cè)字母列表時(shí),實(shí)現(xiàn)左側(cè)城市列表的滾動(dòng)到可視區(qū)域,這時(shí)需要 scroll-into-view="childViewId"
// 點(diǎn)擊右側(cè)的字母 letterClick(letter, i) { this.letterIndex = i; this.currentIndex = i; this.childViewId = letter; setTimeout(() => { this.letterIndex = -1; }, 500); // 0.5秒后浮出的首字母圓圈消失 },
第四步:實(shí)現(xiàn)滑動(dòng)左側(cè),右側(cè)聯(lián)動(dòng)。
當(dāng)滑動(dòng)城市列表時(shí),需要判斷當(dāng)前的滾動(dòng)高度,在哪個(gè)字母范圍內(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; }, // 計(jì)算滾動(dòng)距離 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"); // 實(shí)例化API核心類 qqmapsdk = new QQMapWX({ key: MAP_KEY, }); // 獲取全國(guó)的城市列表 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(); // 獲取各個(gè)字母分類的塊高度 setTimeout(() => { let query = wx.createSelectorQuery().in(this); query .selectAll(".cityList") .boundingClientRect((data) => { console.log(data, "各個(gè)城市分類的高度"); 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; }, // 點(diǎn)擊右側(cè)的字母 letterClick(letter, i) { this.letterIndex = i; this.currentIndex = i; this.childViewId = letter; setTimeout(() => { this.letterIndex = -1; }, 500); }, // 計(jì)算每個(gè)區(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; }, // 計(jì)算滾動(dòng)距離 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); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Javascript 完美運(yùn)動(dòng)框架(逐行分析代碼,讓你輕松了運(yùn)動(dòng)的原理)
這篇文章主要介紹了Javascript 完美運(yùn)動(dòng)框架,逐行分析代碼,讓你輕松了運(yùn)動(dòng)的原理,需要的朋友可以參考下2015-01-01微信小程序動(dòng)態(tài)生成二維碼的實(shí)現(xiàn)代碼
這篇文章主要介紹了微信小程序動(dòng)態(tài)生成二維碼的實(shí)現(xiàn)代碼,需要的朋友可以參考下2018-07-07客戶端JavaScript的線程池設(shè)計(jì)詳解
這篇文章主要為大家介紹了客戶端JavaScript的線程池設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01JavaScript+Canvas實(shí)現(xiàn)繪制音頻可視化波形圖
這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript和Canvas實(shí)現(xiàn)繪制音頻可視化波形圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02小程序?qū)崿F(xiàn)搜索界面 小程序?qū)崿F(xiàn)推薦搜索列表效果
這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)搜索界面,小程序?qū)崿F(xiàn)推薦搜索列表效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05JavaScript在圖片繪制文字兩種方法的實(shí)現(xiàn)與對(duì)比
這篇文章主要為大家詳細(xì)介紹了前端實(shí)現(xiàn)在圖片上繪制文字的兩種思路,支持即粘即貼即用,文中的示例代碼講解詳細(xì),需要的小伙伴可以了解下2024-03-03layui select 禁止點(diǎn)擊的實(shí)現(xiàn)方法
今天小編就為大家分享一篇layui select 禁止點(diǎn)擊的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09