微信小程序(六)定位搜索

发布于:2024-04-16 ⋅ 阅读:(32) ⋅ 点赞:(0)

一、引言

        作者上一章讲了微信小程序的地图实现微信小程序(五)地图-CSDN博客,但是还有一个功能是和地图紧密结合的,那就是位置搜索定位,这里作者讲讲实现和原理,包括城市筛选。

二、定位搜索实现

1、位置搜索样式

        这个其实就是样式啦,不是固定要和作者一样的

        上面一个搜索框,下面展示搜索到的相关位置

<view class="top">
                <view class="back iconfont icon-fanhui" bindtap="back1"></view>
                <view class="search-box {{addListShow?'search-box1':''}}">
                    <view class="region" bindtap="chooseCity">{{currentRegion.district}}</view>
                    <view class="shu"></view>
                    <input class="input-box" bindinput="getsuggest" placeholder="请输入目标位置"></input>
                </view>
            </view>
            <!--关键词输入提示列表渲染-->
            <view class="add-list-box">
                <scroll-view class="add-list" scroll-y>
                    <view class="add-item" wx:for="{{suggestion}}" wx:key="index">
                        <!--绑定回填事件-->
                        <view bindtap="backfill" id="{{index}}" data-name="{{item.title}}">
                            <!--根据需求渲染相应数据-->
                            <!--渲染地址title-->
                            <view class="title">{{item.title}}</view>
                            <!--渲染详细地址-->
                            <view class="add">{{item.addr}}</view>
                        </view>
                    </view>
                </scroll-view>

2、拖动地图

        随着地图拖拽,显示的附近位置也会改变

<cover-view class="top">
                    <cover-view class="back" bindtap="back1">
                        <cover-image src="/static/images/detail_back.png"></cover-image>
                    </cover-view>
                    <cover-view class="search-box">
                        <cover-view class="region" bindtap="chooseCity">{{currentRegion.district}}</cover-view>
                        <cover-view class="shu"></cover-view>
                        <cover-view class="placeholder" bindtap="showAddList">请输入地址</cover-view>
                    </cover-view>
                </cover-view>
                <cover-view class="map-prompt">您可拖动地图, 标记准确位置</cover-view>
                <cover-image class="current-site-icon" src="/static/images/my_marker.png"></cover-image>
                <cover-view class="reload" bindtap="reload">
                    <cover-view class="center1">
                        <cover-view class="center2"></cover-view>
                    </cover-view>
                </cover-view>

3、附近位置样式

        这里展示附近的位置,最终选定之后可以点击位置确认

<scroll-view class="near-list" scroll-y>
                <!--绑定回填事件-->
                <view class="near-item" wx:for="{{nearList}}" wx:key="index">
                    <view class="current-site iconfont icon-location" wx:if="{{index == selectedId }}"></view>
                    <!--根据需求渲染相应数据-->
                    <view bindtap="chooseCenter" id="{{index}}" data-name="{{item.title}}">
                        <!--渲染地址title-->
                        <view class="title {{ index == selectedId?'title1':'' }}">{{item.title}}</view>
                        <!--渲染详细地址-->
                        <view class="add {{ index == selectedId?'add1':'' }}">{{item.addr}}</view>
                    </view>
                </view>
            </scroll-view>
            <view class="bottom-box">
                <button bindtap="selectedOk">确认定位</button>
            </view>

4、搜索附近位置

        是根据选中的位置的经纬度进行搜索的,后端数据在腾讯地图

getsuggest: function (e) {
        var _this = this;
        var keyword = e.detail.value;
        _this.setData({
            addListShow: true
        })
        //调用关键词提示接口
        qqmapsdk.getSuggestion({
            //获取输入框值并设置keyword参数
            keyword: keyword, //用户输入的关键词,可设置固定值,如keyword:'KFC'
            location: _this.data.latitude + ',' + _this.data.longitude,
            page_size: 20,
            page_index: 1,
            //region:'北京', //设置城市名,限制关键词所示的地域范围,非必填参数
            success: function (res) {//搜索成功后的回调
                //console.log(res);
                var sug = [];
                for (var i = 0; i < res.data.length; i++) {
                    sug.push({ // 获取返回结果,放到sug数组中
                        title: res.data[i].title,
                        id: res.data[i].id,
                        addr: res.data[i].address,
                        province: res.data[i].province,
                        city: res.data[i].city,
                        district: res.data[i].district,
                        latitude: res.data[i].location.lat,
                        longitude: res.data[i].location.lng
                    });
                }
                _this.setData({ //设置suggestion属性,将关键词搜索结果以列表形式展示
                    suggestion: sug,
                    nearList: sug,
                    keyword: keyword
                });
            },
            fail: function (error) {
                //console.error(error);
            },
            complete: function (res) {
                //console.log(res);
            }
        });
    },
nearby_search: function () {
        var self = this;
        wx.hideLoading();
        wx.showLoading({
            title: '加载中'
        });
        // 调用接口
        qqmapsdk.search({
            keyword: self.data.keyword,
            location: self.data.latitude + ',' + self.data.longitude,
            page_size: 20,
            page_index: 1,
            success: function (res) { //搜索成功后的回调
                //console.log(res.data)
                var sug = [];
                for (var i = 0; i < res.data.length; i++) {
                    sug.push({ // 获取返回结果,放到sug数组中
                        title: res.data[i].title,
                        id: res.data[i].id,
                        addr: res.data[i].address,
                        province: res.data[i].ad_info.province,
                        city: res.data[i].ad_info.city,
                        district: res.data[i].ad_info.district,
                        latitude: res.data[i].location.lat,
                        longitude: res.data[i].location.lng
                    });
                }
                self.setData({
                    selectedId: 0,
                    centerData: sug[0],
                    nearList: sug,
                    suggestion: sug
                })
                self.addMarker(sug[0]);
            },
            fail: function (res) {
                //console.log(res);
            },
            complete: function (res) {
                //console.log(res);
            }
        });
    },

5、地图拖动

        根据拖动到的经纬度再次进行搜索

mapChange: function (e) {
        let self = this;
        if (e.type == 'end' && (e.causedBy == 'scale' || e.causedBy == 'drag')) {
            self.mapCtx.getCenterLocation({
                success: function (res) {
                    //console.log(res)
                    self.setData({
                        nearList: [],
                        latitude: res.latitude,
                        longitude: res.longitude,
                    })
                    self.nearby_search();
                }
            })
        }

    },

6、标记地图定位

addMarker: function (data) {
        //console.log(data)
        //console.log(data.title)
        var mks = [];
        mks.push({ // 获取返回结果,放到mks数组中
            title: data.title,
            id: data.id,
            addr: data.addr,
            province: data.province,
            city: data.city,
            district: data.district,
            latitude: data.latitude,
            longitude: data.longitude,
            iconPath: "/images/my_marker.png", //图标路径
            width: 25,
            height: 25
        })
        this.setData({ //设置markers属性,将搜索结果显示在地图中
            markers: mks,
            currentRegion: {
                province: data.province,
                city: data.city,
                district: data.district,
            }
        })
        wx.hideLoading({});
    },

7、效果

三、选择省市区实现

1、选择省市区样式

<view class="region-top">
                    <view class="region-back iconfont icon-fanhui" bindtap="back2"></view>
                    <view class="title">选择城市</view>
                </view>
                <view class="region-tabs">
                    <text class="tab" bindtap="showProvince">{{currentProvince}}</text>
                    <text class="tab" bindtap="showCity" >{{currentCity}}</text>
                    <text class="tab" bindtap="showDistrict" >{{currentDistrict}}</text>
                </view>
                <scroll-view scroll-y style="height:1050rpx;">
                    <view class="region-list" wx:if="{{regionShow.province}}">
                        <view class="region-item" wx:for="{{regionData.province}}" wx:key="index">
                            <view data-id="{{item.id}}" data-name="{{item.fullname}}" bindtap="selectProvince">
                                <text>{{item.fullname}}</text>
                            </view>
                        </view>
                    </view>
                    <view class="region-list" wx:if="{{regionShow.city}}">
                        <view class="region-item" wx:for="{{regionData.city}}" wx:key="index">
                            <view data-id="{{item.id}}" data-name="{{item.fullname}}" bindtap="selectCity">
                                <text>{{item.fullname}}</text>
                            </view>
                        </view>
                    </view>
                    <view class="region-list" wx:if="{{regionShow.district}}">
                        <view class="region-item" wx:for="{{regionData.district}}" wx:key="index">
                            <view data-id="{{item.id}}" data-name="{{item.fullname}}"
                                  data-latitude="{{item.location.lat}}" data-longitude="{{item.location.lng}}"
                                  bindtap="selectDistrict">
                                <text>{{item.fullname}}</text>
                            </view>
                        </view>
                    </view>

2、省市区缓存

        省市区相当于先是几个层级的筛选,所以得先从地图查一下进行级联缓存,不然每次调用地图卡死了,用户体验会很差

getRegionData: function () {
        let self = this;
        console.log('调用获取城市列表接口')
        //调用获取城市列表接口
        qqmapsdk.getCityList({
            success: function (res) {//成功后的回调
                console.log(res)
                let provinceArr = res.result[0];
                let cityArr = [];
                let districtArr = [];
                for (var i = 0; i < provinceArr.length; i++) {
                    var name = provinceArr[i].fullname;
                    if (self.data.currentRegion.province == name) {
                        // if (name == '北京市' || name == '天津市' || name == '上海市' || name == '重庆市') {
                        //     cityArr.push(provinceArr[i])
                        // } else {
                        qqmapsdk.getDistrictByCityId({
                            // 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
                            id: provinceArr[i].id,
                            success: function (res) {//成功后的回调
                                //console.log(res);
                                cityArr = res.result[0];
                                console.log('setData');
                                self.setData({
                                    regionData: {
                                        province: provinceArr,
                                        city: cityArr,
                                        district: districtArr
                                    }
                                })
                            },
                            fail: function (error) {
                                console.error(error);
                            },
                            complete: function (res) {
                                console.log(res);
                            }
                        });
                    }
                    // }
                }
                console.log('now res:{}', res);
                console.log('self.data.currentRegion:{}', JSON.stringify(self.data.currentRegion));
                
            },
            fail: function (error) {
                console.error(error);
            },
            complete: function (res) {
                console.log(res);
            }
        });
    },

3、打开省市区页面

        

chooseCity: function () {
        let self = this;
        self.getRegionData();
        self.setData({
            chooseCity: true,
            regionShow: {
                province: true,
                city: false,
                district: false
            },
            currentProvince: self.data.currentRegion.province,
            currentCity: self.data.currentRegion.city,
            currentDistrict: self.data.currentRegion.district,
        })
    },

4、选择省市区

showProvince: function () {
        console.log('showProvince')
        console.log(this.data.regionData.province)
        this.setData({
            regionShow: {
                province: true,
                city: false,
                district: false
            }
        })
    },
    //选择城市
    showCity: function () {
        this.setData({
            regionShow: {
                province: false,
                city: true,
                district: false
            }
        })
    },
    //选择地区
    showDistrict: function () {
        this.setData({
            regionShow: {
                province: false,
                city: false,
                district: true
            }
        })
    },

selectProvince: function (e) {
        //console.log(e)
        let self = this;
        let id = e.currentTarget.dataset.id;
        let name = e.currentTarget.dataset.name;
        self.setData({
            currentProvince: name,
            currentCity: '请选择城市',
        })
        if (name == '北京市' || name == '天津市' || name == '上海市' || name == '重庆市') {
            var provinceArr = self.data.regionData.province;
            var cityArr = [];
            for (var i = 0; i < provinceArr.length; i++) {
                if (provinceArr[i].fullname == name) {
                    cityArr.push(provinceArr[i])
                    self.setData({
                        regionData: {
                            province: self.data.regionData.province,
                            city: cityArr,
                            district: self.data.regionData.district
                        }
                    })
                    self.showCity();
                    return;
                }
            }
        } else {
            let bj = self.data.regionShow;
            self.getById(id, name, bj)
        }
    },
    //选择城市之后操作
    selectCity: function (e) {
        let self = this;
        let id = e.currentTarget.dataset.id;
        let name = e.currentTarget.dataset.name;
        self.setData({
            currentCity: name,
            currentDistrict: '请选择城市',
        })
        let bj = self.data.regionShow;
        self.getById(id, name, bj)
    },
    //选择区县之后操作
    selectDistrict: function (e) {
        let self = this;
        let id = e.currentTarget.dataset.id;
        let name = e.currentTarget.dataset.name;
        let latitude = e.currentTarget.dataset.latitude;
        let longitude = e.currentTarget.dataset.longitude;
        self.setData({
            currentDistrict: name,
            latitude: latitude,
            longitude: longitude,
            currentRegion: {
                province: self.data.currentProvince,
                city: self.data.currentCity,
                district: name
            },
            chooseCity: false,
            keyword: self.data.defaultKeyword
        })
        self.nearby_search();
    },
    //根据选择省市加载市区列表
    getById: function (id, name, bj) {
        let self = this;
        qqmapsdk.getDistrictByCityId({
            // 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
            id: id, //对应接口getCityList返回数据的Id,如:北京是'110000'
            success: function (res) {//成功后的回调
                //console.log(res);
                if (bj.province) {
                    self.setData({
                        regionData: {
                            province: self.data.regionData.province,
                            city: res.result[0],
                            district: self.data.regionData.district
                        }
                    })
                    self.showCity();
                } else if (bj.city) {
                    self.setData({
                        regionData: {
                            province: self.data.regionData.province,
                            city: self.data.regionData.city,
                            district: res.result[0]
                        }
                    })
                    self.showDistrict();
                } else {
                    self.setData({
                        chooseCity: false,
                    })
                }
            },
            fail: function (error) {
                //console.error(error);
            },
            complete: function (res) {
                //console.log(res);
            }
        });
    },

4、确认定位

        这个要看啦,作者是在同一个页面,只是把地图当成一个弹窗,所以只要关闭弹窗就行,变量设置到这个页面了

        如果地图是另外一个页面,还要跳转的时候把数据带过去

5、效果

 四、总结

        定位的搜索和省市区筛选基本就这样了,后端是依赖腾讯地图的,作者在之前的文章也写了怎么引用腾讯地图,有疑问的小伙伴欢迎评论区私聊。