在一些需求中杉适,我們需要有一個(gè)全國(guó)城市的列表供我們選擇谎倔,并且可以獲得對(duì)應(yīng)的經(jīng)緯度坐標(biāo)。
今天猿推,我們就一起來實(shí)現(xiàn)這個(gè)需求片习。
好,我們先看一下我們期望的最終效果蹬叭,如下圖:
我們看到左側(cè)有個(gè)下拉選項(xiàng)藕咏,右側(cè)是供搜索的輸入關(guān)鍵字用到的輸入框。
關(guān)于搜索的需求可以看這個(gè)教程使用高德地圖微信小程序SDK開發(fā)案例-輸入提示(附源碼)
我們今天主要實(shí)現(xiàn)如下需求:
1.頁面布局具垫。
2.進(jìn)入頁面自動(dòng)定位當(dāng)前所在的城市侈离。
3.獲取全國(guó)城市列表,并且按照拼音的首字母排序筝蚕。
4.點(diǎn)擊后獲取對(duì)應(yīng)的經(jīng)緯度卦碾。
5.點(diǎn)擊字母跳轉(zhuǎn)到同一類拼音首字母開始的列表铺坞。
知道的要做的事情,咱們就開始擼代碼~
<view class='list-city'>
<scroll-view scroll-y="true" style="height:100%;" scroll-into-view="{{scrollTopId}}" scroll-with-animation="true" enable-back-to-top="true">
<view class='item'>
<view class='fullname'>當(dāng)前定位城市:{{citySelected}}</view>
</view>
<!-- 熱門城市 -->
<view class='item'>
<view class='py' id="hot">熱門城市</view>
<view class="fullname hot-city" wx:for="{{hotCityData}}" wx:key="key" data-fullname="{{item.fullname}}" data-lat="{{item.location.lat}}" data-lng="{{item.location.lng}}" bindtap='selectCity'>{{item.fullname}}
</view>
</view>
<!-- 全部 -->
<view class='item' wx:for="{{cityData}}" wx:for-index="idx" wx:for-item="group" wx:key="key">
<view class='py' id="{{idx}}">{{idx}}</view>
<view class="fullname" wx:for="{{group}}" wx:key="key" data-fullname="{{item.fullname}}" data-lat="{{item.location.lat}}" data-lng="{{item.location.lng}}" bindtap='selectCity'>{{item.fullname}}
</view>
</view>
</scroll-view>
<!-- 首字母 -->
<view class='city-py' bindtouchstart="tStart" bindtouchend="tEnd" catchtouchmove="tMove">
<view wx:for="{{_py}}" wx:key="key" bindtouchstart="getPy" bindtouchend="setPy" id="{{item}}">{{item == 'hot' ? "★" : item}}
</view>
</view>
</view>
這是頁面的主要結(jié)構(gòu)洲胖,我們分為三大塊济榨,熱門城市,全部城市绿映,還是有首字母擒滑。
我們使用循環(huán)來展示城市名稱,并且使用data-fullname="{{item.fullname}}" data-lat="{{item.location.lat}}" data-lng="{{item.location.lng}}" bindtap='selectCity'來記錄對(duì)應(yīng)城市的經(jīng)緯度叉弦,同時(shí)綁定了點(diǎn)擊事件來獲取經(jīng)緯度和城市名稱丐一。
至于頁面右側(cè)字母索引綁定的事件比較復(fù)雜,我們到后面詳細(xì)來講淹冰。
頁面的骨架有了库车,接著可以寫幾行css來美化下頁面。然后我們正式進(jìn)入主要階段樱拴。
我們通過高德地圖微信小程序SDKhttps://lbs.amap.com/api/wx/guide/get-data/regeo提供的接口來直接獲取詳細(xì)地址信息柠衍。
onLoad: function() {
var that = this;
var myAmapFun = new amapFile.AMapWX({key:'高德Key'});
myAmapFun.getRegeo({
success: function(data){
//成功回調(diào),獲得當(dāng)前所在城市名稱
let city = data.regeocodeData.addressComponent.province;
},
fail: function(info){
//失敗回調(diào)
console.log(info)
}
})
},
或者我們也可以使用騰訊地圖微信小程序SDK https://lbs.qq.com/qqmap_wx_jssdk/method-reverseGeocoder.html 提供的接口來獲取晶乔。因?yàn)槲覀兘酉聛砭鸵褂抿v訊地圖微信小程序SDK珍坊。
第二步我們實(shí)現(xiàn)了,接下來獲取全國(guó)城市列表正罢。
是的阵漏,https://lbs.qq.com/qqmap_wx_jssdk/method-getcitylist.html,在頁面上我們很快發(fā)現(xiàn)了這個(gè)接口腺怯,我們直接調(diào)用袱饭。然而我直接將數(shù)據(jù)保存到了js文件川无。
https://raw.githubusercontent.com/749264345/wechat-miniapp-map/master/libs/city.js
我們根據(jù)數(shù)據(jù)直接賦值到頁面上的參數(shù)呛占,結(jié)果很順利。
很快懦趋,我們到了第四步晾虑,我們?yōu)榱斜淼氖录砑雍瘮?shù)。
//選擇城市
selectCity: function (e) {
var dataset = e.currentTarget.dataset;
this.setData({
citySelected: dataset.fullname,
location: {
latitude: dataset.lat,
longitude: dataset.lng
}
});
}
我們獲取到剛才我們?cè)O(shè)置的三個(gè)屬性仅叫,并且保存他們帜篇,以備后續(xù)使用。
是的诫咱,很簡(jiǎn)單笙隙,我們現(xiàn)在差后一步。當(dāng)我們點(diǎn)擊C的時(shí)候坎缭,頁面滾動(dòng)到重慶市竟痰,點(diǎn)擊W的時(shí)候頁面滾動(dòng)到武清區(qū)签钩。。坏快。铅檩。以此類推。
于是我們字母索引添加2個(gè)事件莽鸿,bindtouchstart="getPy" bindtouchend="setPy"昧旨。
//獲取點(diǎn)擊的字母,在頁面放大上展示
getPy: function (e) {
this.setData({
hidden: false,
showPy: e.target.id,
})
},
//將設(shè)置到字母祥得,賦值到scrollTopId
setPy: function (e) {
this.setData({
hidden: true,
scrollTopId: this.data.showPy
})
},
不急兔沃,我們慢慢來,這里有幾個(gè)問題级及。
1.賦值到scrollTopId是為什么粘拾?
<scroll-view scroll-y="true" scroll-into-view="{{scrollTopId}}" scroll-with-animation="true" enable-back-to-top="true">
我們看到我們使用了小程序的scroll-view組件,我們將scrollTopId這個(gè)值賦值給了scroll-into-view屬性创千,scroll-with-animation="true" 并且滾動(dòng)時(shí)有滑動(dòng)效果缰雇。
這個(gè)類似于網(wǎng)頁中的錨點(diǎn),給scroll-into-view賦一個(gè)值X以后追驴,頁面將滾動(dòng)到子元素設(shè)置屬性id='x'的地方械哟。所以我們看到:
<view class='py' id="{{idx}}">{{idx}}</view>
我們?yōu)榱斜碇械乃饕砑恿藢傩詉d。
第二個(gè)問題殿雪,為什么綁定2個(gè)事件暇咆,而不是一個(gè)點(diǎn)擊事件bindtap
這里關(guān)系到我們下一個(gè)需求,就是我們手指點(diǎn)擊索引那一欄之后丙曙,不離開爸业,通過上下滑動(dòng),可以快速預(yù)覽城市列表亏镰,當(dāng)手指離開之后扯旷,列表滾動(dòng)到手指最后停留的那個(gè)字母位置。
而且索抓,我們必須將滑動(dòng)的交互事件綁定到字母索引的外層钧忽,就像我們看到的這樣:
<view class='city-py' bindtouchstart="tStart" bindtouchend="tEnd" catchtouchmove="tMove">
<view wx:for="{{_py}}" wx:key="key" bindtouchstart="getPy" bindtouchend="setPy" id="{{item}}">
{{item == 'hot' ? "★" : item}}
</view>
</view>
當(dāng)我們將getPy有setPy合并到一個(gè)事件中時(shí),我們將無法看到索引字母在頁面中間的效果逼肯,當(dāng)我們手指觸摸到的時(shí)候顯示耸黑,離開的時(shí)候消失,這里是2個(gè)事件篮幢。
就像這樣大刊,中間字母的預(yù)覽效果。
如果我們將這2個(gè)事件合并到父元素上時(shí)三椿,我們將很難獲取到準(zhǔn)確的字母索引值缺菌,也就是id曲尸。
我們?cè)诟冈厣咸砑恿巳齻€(gè)事件,
//滑動(dòng)時(shí)
tMove: function (e) {
var y = e.touches[0].clientY,
offsettop = e.currentTarget.offsetTop,
that = this;
//判斷選擇區(qū)域,只有在選擇區(qū)才會(huì)生效
if (y > offsettop) {
var num = parseInt((y - offsettop) / 12);
this.setData({
showPy: that.data._py[num]
})
};
},
//觸發(fā)全部開始選擇
tStart: function () {
this.setData({
hidden: false
})
},
//觸發(fā)結(jié)束選擇
tEnd: function () {
this.setData({
hidden: true,
scrollTopId: this.data.showPy
})
},
當(dāng)我們?cè)谒饕且粰谏舷禄瑒?dòng)手指的同時(shí)男翰,計(jì)算出當(dāng)前手指可能觸碰到的字母另患,并且當(dāng)且僅當(dāng)手指在元素范圍內(nèi)的時(shí)候觸發(fā)。
可能你覺這些代碼有部分冗余蛾绎,是否可以將tStart與tEnd舍去昆箕?答案是可以的,功能不受影響租冠,但是當(dāng)你在上下滑動(dòng)的過程中鹏倘,可以明顯感到中間索引的提示有明顯的卡頓,這不是我們想要的顽爹。
代碼寫到這里纤泵,基本上已經(jīng)差不多了。
如有更好的實(shí)現(xiàn)方式希望在評(píng)論區(qū)能夠分享镜粤。
詳細(xì)案例請(qǐng)搜索微信小程序:52魔都
源碼地址:https://github.com/749264345/wechat-weapp-map