微信小程序?qū)崿F(xiàn)按字母排列選擇城市功能
實現(xiàn)效果預覽

實現(xiàn)思想
利用小程序騰訊地圖將所有城市查出來,并將其渲染至頁面(https://lbs.qq.com/qqmap_wx_jssdk/index.html)(其中字母欄也根據(jù)獲取到的數(shù)據(jù)變化)
其中涉及三個交互(點擊字母時滾動到相應位置;滑動觸摸字母時,需滾動到相應位置,并有當前哪個字母的提示,且有震動感;手動滑動頁面時,需將當前對應的字母選中)
滑動觸摸字母時,首先要得到所有字母所在塊的高度,再平均的獲取到每個字母的高度。當觸摸滾動時,拿到pageY(距離文檔左上角的距離,具體解釋官網(wǎng)有https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#touches)
計算出所有字母內(nèi)容的高度,并存為一個數(shù)組
利用pageY計算出可能到達的字母位置的下標(pageY-字母欄的top值/每個字母的高度)
將計算出的下標所對應的字母內(nèi)容高度賦值給scroll-top值
手動滾動列表時,根據(jù)滾動的距離計算出當前滾動的下標值,將字母數(shù)組的對應的下標值做處理
需要注意setData不能頻繁使用,所以在使用的時候,需要做處理和優(yōu)化
實現(xiàn)知識點
字母滾動到相應位置需使用scroll-view組件中的scroll-into-view 設置其子元素的id值
滑動觸摸字母,需使用小程序事件touchmove事件和touchend事件
手動滑動頁面時,需使用scroll-view中的scroll-top屬性設置豎向滾動條位置
代碼
wxml
<!--pages/findHome/selectCity/index.wxml-->
<view class="selectCity">
<view class="searchCity">
<input placeholder="輸入城市名進行搜索" bindinput="getSuggest" bindfocus="inputFocus"></input>
</view>
<view class="cityContainer" style="padding-top: {{searchCity}}px">
<scroll-view scroll-y="true" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}" bindscroll="scroll" style="height: 100%" scroll-with-animation="ture">
<block wx:for="{{citys}}" wx:for-index="key" wx:for-item="value" wx:key="key">
<view class="cityItem">
<view class="citytype" id="{{value.id}}">{{key}}</view>
<block wx:for="{{value.data}}" wx:for-key="i" wx:for-item="ele" wx:key="i">
<view class="cityDetail" data-name="{{ele.fullname}}" bindtap="confrimCity">{{ele.fullname}}</view>
</block>
</view>
</block>
</scroll-view>
<view class="cityAZ">
<block wx:for="{{letter}}" wx:key="{{id}}">
<view bindtap="letterClick" class="AZ {{!touchFlag && activeAZ == item.id ? 'activeAZ' : ''}}" data-id="{{item.id}}" catchtouchmove="whenTouch" catchtouchend="touchEnd" id="{{item.id}}">{{item.name}}
<view class="AZInfo" wx:if="{{touchFlag && activeAZ == item.id}}">
{{item.name}}
<view class="trigle"></view>
</view>
</view>
</block>
</view>
</view>
</view>
wxss
/* pages/findHome/selectCity/index.wxss */
.selectCity {
width: 100vw;
height: 100vh;
}
.searchCity {
height: 70rpx;
line-height: 70rpx;
width: 100%;
padding: 0 24rpx;
position: fixed;
top: 0;
left: 0;
background: #fff;
z-index: 10;
}
.cityContainer {
height: 100%;
}
.cityItem {
padding: 0 70rpx 0 24rpx;
}
.citytype {
height: 70rpx;
background: #F5F5F5;
line-height: 70rpx;
padding: 0 24rpx;
}
.cityDetail {
height: 80rpx;
line-height: 80rpx;
padding: 0 24rpx;
border-top: 1px solid #DCDCDC;
border-bottom: none;
}
.cityDetail:last-child {
border-bottom: 1px solid #DCDCDC;
}
.cityAZ {
position: fixed;
top: 136rpx;
right: 0;
font-size: 28rpx;
padding: 0 24rpx;
/* background: #fff; */
width: 40rpx;
text-align: center;
}
.AZ {
position: relative;
border-radius: 50%;
}
.activeAZ {
background: orange;
color: #fff;
}
.AZInfo {
width: 70rpx;
height: 70rpx;
border-radius: 50%;
text-align: center;
color: #fff;
line-height: 70rpx;
background: orange;
position: absolute;
left: -94rpx;
top: -14rpx;
}
.trigle {
width: 0;
height: 0;
border: 32rpx solid orange;
border-right: none;
border-top-color: transparent;
border-bottom-color: transparent;
position: absolute;
top: 4rpx;
right: -9rpx;
}
js
// pages/findHome/selectCity/index.js
let cityDatas = require('../../../utils/cityData.js');
let QQMapWX = require('../../../libs/qqmap-wx-jssdk.js');
let qqmapsdk = new QQMapWX({
key: '4WKBZ-ADX36-MGNS4-E6TFJ-Q6JJE-YBF2A'
});
Page({
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
citys: {},//獲取到的所有城市
letter: [], //獲取到的所有字母
searchCity: 0,
toView: '', //點擊跳轉(zhuǎn)的id
scrollTop: '',
citysHeight: [],//所有字母大模塊的top
azHeight: 0, //每個字母平均的高度
azTop: 0,
index: '',
activeAZ: 'A1',
touchFlag: false
},
letterClick: function (e) {
this.setData({
touchFlag: false,
toView: e.currentTarget.dataset.id
// activeAZ: e.currentTarget.dataset.id,
})
},
confrimCity() {
wx.switchTab({
url: '/pages/findHome/index',
})
},
whenTouch(e) {
let index = 0;
if((e.touches[0].pageY - this.data.azTop) % this.data.azHeight == 0){
index = (e.touches[0].pageY - this.data.azTop) / this.data.azHeight
}else {
index = parseInt((e.touches[0].pageY - this.data.azTop) / this.data.azHeight);
if(this.data.index !== index && index < this.data.letter.length) {
this.data.index = index;
this.setData({
scrollTop: this.data.citysHeight[index],
activeAZ: this.data.letter[index].id,
touchFlag: true
})
wx.vibrateShort();
}
}
},
touchEnd() {
setTimeout(()=>{
this.setData({
touchFlag: false
})
},600)
},
scroll(e) {
let scrollHeight = e.detail.scrollTop;
let index = this.calculateIndex(this.data.citysHeight, scrollHeight);
if (this.data.index !== index && index < this.data.letter.length) {
this.setData({
index: index,
activeAZ: this.data.letter[index].id,
touchFlag: false
})
}
},
calculateIndex(arr, scrollHeight) {
let index = 0;
for (let i = 0; i < arr.length; i++) {
if (scrollHeight >= arr[i - 1] && scrollHeight < arr[i]) {
index = i - 1;
break;
}else if(scrollHeight >= arr[arr.length-1]) {
index = arr.length - 1;
break;
}else if(0 < scrollHeight < arr[0]) {
index = 0
}
}
return index;
},
getSuggest(e) {
console.log(e)
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
onLoad: function (options) {
let query = wx.createSelectorQuery();
query.select('.searchCity').boundingClientRect(rect => {
this.setData({
searchCity: rect.height
})
}).exec();
qqmapsdk.getCityList({
success: (res) => {//成功后的回調(diào)
res.result[1].forEach(ele => {
//如果城市對象中已經(jīng)存在該字母開頭的
if (this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()]){
this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()].data.push(ele);
}else {
this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()] = {id: '',data: []};
this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()].id = ele.pinyin[0].charAt(0).toUpperCase()+1;
this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()].data.push(ele);
}
})
let newArr = Object.keys(this.data.citys).sort();
let sortCity = {};
newArr.forEach(ele => {
this.data.letter.push({name: ele, id: ele+1})
sortCity[ele] = this.data.citys[ele]
})
this.setData({
citys: sortCity,
letter: this.data.letter,
citysHeight: []
});
//獲取個字母大模塊的top值
query.selectAll('.cityItem').boundingClientRect((rect) => {
this.data.citysHeight = [];
rect.forEach(ele => {
this.data.citysHeight.push(ele.top - this.data.searchCity)
})
}).exec();
//獲取已有字母的高度
let winH = wx.getSystemInfoSync().windowHeight;
query.select('.cityAZ').boundingClientRect((rect) => {
this.data.azHeight = rect.height / this.data.letter.length;
this.data.azTop = rect.top;
}).exec();
},
fail: function (error) {
console.error(error);
},
complete: function (res) {
}
});
this.setData({
toView: 'A1'
});
}
})
總結
以上所述是小編給大家介紹的微信小程序?qū)崿F(xiàn)按字母排列選擇城市,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關文章
JavaScript實現(xiàn)的購物車效果可以運用在好多地方
JavaScript實現(xiàn)的購物車效果,當然這個效果可以運用在好多地方,比如好友的選擇,人力資源模塊等等,需要的朋友可以參考下2014-05-05
js模式化窗口問題![window.dialogArguments]
這篇文章主要介紹了js模式化窗口問題![window.dialogArguments],需要的朋友可以參考下2016-10-10
JavaScript實現(xiàn)一鍵復制文本功能的示例代碼
這篇文章主要為大家介紹兩種javascript實現(xiàn)文本復制(將文本寫入剪貼板)的方法,文中的示例代碼講解詳細,大家可以根據(jù)需求特點選用2023-03-03
uniapp?動態(tài)組件實現(xiàn)Tabs標簽切換組件(喜馬拉雅app作為案例)
本文以喜馬拉雅app作為案例給大家詳解講解uniapp?動態(tài)組件實現(xiàn)Tabs標簽切換組件功能,在uniapp中實現(xiàn)動態(tài)組件切換需看uniapp是否支持,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-10-10

