微信小程序实现腾讯地图定位功能-demo
1,去腾讯地图官方api官网注册账号
官网地址:https://lbs.qq.com/
1,申请开发者密钥(key):申请密钥
2,开通webserviceAPI服务:控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebServiceAPI -> 保存
(小程序SDK需要用到webserviceAPI的部分服务,所以使用该功能的KEY需要具备相应的权限)
3,下载微信小程序JavaScriptSDK,微信小程序JavaScriptSDK v1.1 JavaScriptSDK v1.2
4,安全域名设置,在小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加https://apis.map.qq.com
小程序示例
wxml
<!--pages/shopMap/shopMap.wxml-->
<!--绑定点击事件-->
<!--绑定输入事件-->
<view wx:if="{{addListShow}}">
<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 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>
</view>
</view>
<view wx:if="{{!addListShow && !chooseCity}}">
<!--地图容器-->
<map id="myMap" style="width:100%;height:300px;" longitude="{{longitude}}" latitude="{{latitude}}" scale="17"
bindregionchange="mapChange">
<cover-view class="top">
<!-- <cover-view class="back" bindtap="back1">
<cover-image src="https://img-blog.csdnimg.cn/2019040311084374.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="http://imghz5.linkunst.com/330109011/20210425/90141source60850e109b557.png"></cover-image>
<cover-view class="reload" bindtap="reload">
<cover-view class="center1">
<cover-view class="center2"></cover-view>
</cover-view>
</cover-view>
</map>
<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>
</view>
<view class="region-box" wx:if="{{chooseCity}}">
<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" wx:if="{{!regionShow.province}}" bindtap="showCity">{{currentCity}}</text>
<text class="tab" bindtap="showDistrict" wx:if="{{regionShow.district}}"
bindtap="showDistrict">{{currentDistrict}}</text>
</view>
<scroll-view scroll-y style="height:1150rpx;">
<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>
</scroll-view>
</view>
wxss
/* pages/shopMap/shopMap.wxss */
/* @import "../../lib/css/iconfont.wxss"; */
.top {
width: 100%;
height: 80rpx;
line-height: 80rpx;
position: fixed;
top: 0;
left: 0;
padding: 30rpx 20rpx;
z-index: 999;
overflow: hidden;
}
.back {
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
color: #666;
text-align: center;
background: rgb(255,255,255);
font-size: 50rpx;
border-radius: 50%;
float: left;
}
.back cover-image{
width: 50rpx;
height: 50rpx;
display: inline-block;
margin-top: 15rpx;
}
.search-box {
width: 686rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 16rpx;
background: rgb(255,255,255);
margin-left: 10rpx;
float: left;
overflow: hidden;
}
.search-box1 {
border: 1px solid #ccc;
border-radius: 10rpx;
background: #eee;
}
.search-box .region {
width: 199rpx;
line-height: 80rpx;
font-size: 30rpx;
color: #282828;
text-align: center;
float: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.search-box .shu {
width: 1rpx;
height: 50rpx;
background:#ccc;
float: left;
margin-top: 15rpx;
}
.search-box input {
width: 380rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
color: #282828;
padding: 10rpx 20rpx;
box-sizing: border-box;
float: left;
}
.search-box .placeholder{
width: 380rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
color: #ccc;
padding: 0 20rpx;
box-sizing: border-box;
float: left;
}
.add-list-box {
position: absolute;
width: 100%;
height: 100%;
top: 0;
z-index: 998;
padding-top: 150rpx;
background: #fff;
box-sizing: border-box;
overflow: hidden;
}
.add-list {
width: 100%;
height: 1000rpx;
}
.add-item {
line-height: 40rpx;
padding: 30rpx 50rpx;
text-align: left;
border-top: 1px solid #eee;
}
.add-item .title {
color: #282828;
font-size: 32rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.add-item .add {
color: #707070;
font-size: 24rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.current-site-icon {
width: 50rpx;
height: 50rpx;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.near-list {
height: 800rpx;
padding-bottom: 100rpx;
box-sizing: border-box;
}
.near-item {
line-height: 40rpx;
padding: 30rpx 50rpx 30rpx 50rpx;
text-align: left;
border-bottom: 1px solid #eee;
position: relative;
}
.current-site {
font-size: 40rpx;
color: #3095F9;
position: absolute;
top: 40rpx;
left: 30rpx;
}
.near-item .title {
color: #282828;
font-size: 32rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.near-item .add {
color: #707070;
font-size: 24rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.near-item .title1 {
color: #3095F9;
}
.near-item .add1 {
color: #3095F9;
}
.bottom-box {
width: 100%;
padding: 20rpx;
background: #fff;
box-sizing: border-box;
position: fixed;
left: 0;
bottom: 100rpx;
z-index: 88;
overflow: hidden;
}
.bottom-box button{
width: 100%;
height: 80rpx;
line-height: 50rpx;
border: none;
background: #07409F;
color: #fff;
font-size: 32rpx;
}
.region-box {
width: 100%;
height: 100%;
background: #FFF;
position: fixed;
top: 0;
left: 0;
z-index: 1001;
}
.region-box .region-top {
position: relative;
font-size: 40rpx;
color: #282828;
font-weight: bold;
line-height: 100rpx;
text-align: center;
}
.region-box .region-back {
width: 80rpx;
height: 80rpx;
font-size: 50rpx;
text-align: center;
position: absolute;
top: 0;
left: 0;
}
.region-box .region-tabs{
line-height: 60rpx;
font-size: 20rpx;
}
.region-tabs .tab {
min-width: 100rpx;
max-width: 200rpx;
line-height: 40rpx;
font-size: 24rpx;
color: #3095F9;
text-align: center;
border: 1rpx solid #3095F9;
border-radius: 12rpx;
display: inline-block;
margin: 20rpx 0 20rpx 20rpx;
padding: 3rpx 20rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.region-list .region-item{
font-size: 30rpx;
color: #282828;
line-height: 80rpx;
padding: 10rpx 30rpx;
border-top: 1rpx solid #eee;
}
.map-prompt {
width: 420rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
color: #707070;
text-align: center;
background: #fff;
border-radius: 10rpx;
box-shadow: 0 0 10rpx rgba(0,0,0,0.1);
position: absolute;
bottom: 40rpx;
left: 50%;
transform: translate(-50%,0);
}
.reload {
width: 80rpx;
height: 80rpx;
background: #fff;
border-radius: 10rpx;
box-shadow: 0 0 10rpx rgba(0,0,0,0.1);
position: absolute;
bottom: 30rpx;
right: 30rpx;
}
.reload .center1 {
width: 50rpx;
height: 50rpx;
border: 1rpx solid #3095F9;
border-radius: 50%;
margin: 14rpx auto;
}
.reload .center2 {
width: 25rpx;
height: 25rpx;
background: #3095F9;
border-radius: 50%;
margin: 14rpx auto;
}
js
var QQMapWX = require('../../utils/qqmap-wx-jssdk.min.js');
var qqmapsdk;
Page({
data: {
storeAddress:'',
addListShow: false,
chooseCity: false,
regionShow: {
province: false,
city: false,
district: true
},
regionData: {},
currentRegion: {
province: '选择城市',
city: '选择城市',
district: '选择城市',
},
currentProvince: '选择城市',
currentCity: '选择城市',
currentDistrict: '选择城市',
latitude: '',
longitude: '',
centerData: {},
nearList: [],
suggestion: [],
selectedId: 0,
defaultKeyword: '房产小区',
keyword: ''
},
onLoad: function () {
let self =this;
self.mapCtx = wx.createMapContext('myMap')
// 实例化API核心类
qqmapsdk = new QQMapWX({
key: 'W57BZ-JDB6X-XPA4H-Z76MI-73FF2-24BT4'
});
wx.showLoading({
title: '加载中'
});
//定位
wx.getLocation({
type: 'gcj02',
success(res) {
// console.log(res)
const latitude = res.latitude
const longitude = res.longitude
const speed = res.speed
const accuracy = res.accuracy
//你地址解析
qqmapsdk.reverseGeocoder({
location: {
latitude: latitude,
longitude: longitude
},
success: function (res) {
self.setData({
latitude: latitude,
longitude: longitude,
currentRegion: res.result.address_component,
keyword: self.data.defaultKeyword
})
// 调用接口
self.nearby_search();
},
});
},
fail(err) {
//console.log(err)
wx.hideLoading({});
wx.showToast({
title: '定位失败',
icon: 'none',
duration: 1500
})
setTimeout(function () {
wx.navigateBack({
delta: 1
})
}, 1500)
}
})
},
onReady: function () {
},
//监听拖动地图,拖动结束根据中心点更新页面
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();
}
})
}
},
//重新定位
reload: function () {
this.onLoad();
},
//整理目前选择省市区的省市区列表
getRegionData: function () {
let self = this;
//调用获取城市列表接口
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];
self.setData({
regionData: {
province: provinceArr,
city: cityArr,
district: districtArr
}
})
},
fail: function (error) {
//console.error(error);
},
complete: function (res) {
//console.log(res);
}
});
}
}
}
for (var i = 0; i < res.result[1].length; i++) {
var name = res.result[1][i].fullname;
if (self.data.currentRegion.city == name) {
qqmapsdk.getDistrictByCityId({
// 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
id: res.result[1][i].id,
success: function (res) {//成功后的回调
//console.log(res);
districtArr = res.result[0];
self.setData({
regionData: {
province: provinceArr,
city: cityArr,
district: districtArr
}
})
},
fail: function (error) {
//console.error(error);
},
complete: function (res) {
//console.log(res);
}
});
}
}
},
fail: function (error) {
//console.error(error);
},
complete: function (res) {
//console.log(res);
}
});
},
onShow: function () {
let self = this;
},
//地图标记点
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({});
},
//点击选择搜索结果
backfill: function (e) {
var id = e.currentTarget.id;
let name = e.currentTarget.dataset.name;
for (var i = 0; i < this.data.suggestion.length; i++) {
if (i == id) {
//console.log(this.data.suggestion[i])
this.setData({
centerData: this.data.suggestion[i],
addListShow: false,
latitude: this.data.suggestion[i].latitude,
longitude: this.data.suggestion[i].longitude
});
this.nearby_search();
return;
//console.log(this.data.centerData)
}
}
},
//点击选择地图下方列表某项
chooseCenter: function (e) {
var id = e.currentTarget.id;
let name = e.currentTarget.dataset.name;
for (var i = 0; i < this.data.nearList.length; i++) {
if (i == id) {
this.setData({
selectedId: id,
centerData: this.data.nearList[i],
latitude: this.data.nearList[i].latitude,
longitude: this.data.nearList[i].longitude,
});
this.addMarker(this.data.nearList[id]);
return;
//console.log(this.data.centerData)
}
}
},
//显示搜索列表
showAddList: function () {
this.setData({
addListShow: true
})
},
// 根据关键词搜索附近位置
nearby_search: function () {
var self = this;
wx.hideLoading();
wx.showLoading({
title: '加载中'
});
// 调用接口
qqmapsdk.search({
keyword: self.data.keyword, //搜索关键词
//boundary: 'nearby(' + self.data.latitude + ', ' + self.data.longitude + ', 1000, 16)',
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);
}
});
},
//根据关键词搜索匹配位置
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);
}
});
},
//打开选择省市区页面
chooseCity: function () {
let self = this;
self.getRegionData();
self.setData({
chooseCity: true,
regionShow: {
province: false,
city: false,
district: true
},
currentProvince: self.data.currentRegion.province,
currentCity: self.data.currentRegion.city,
currentDistrict: self.data.currentRegion.district,
})
},
//选择省
showProvince: function () {
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);
}
});
},
//返回上一页或关闭搜索页面
back1: function () {
if (this.data.addListShow) {
this.setData({
addListShow: false
})
}else {
wx.navigateBack({
delta: 1
})
}
},
//关闭选择省市区页面
back2: function () {
this.setData({
chooseCity: false
})
},
//确认选择地址
selectedOk: function () {
let pages = getCurrentPages(); //获取当前页面js里面的pages里的所有信息。
// let prevPage = pages[pages.length - 2];
// console.log(this.data.centerData.addr) //详细地址
let addr = this.data.centerData.addr
wx.setStorageSync('addr', addr)
// prevPage.setData({
// storeAddress: this.data.centerData.title
// })
wx.navigateBack({
delta: 1
})
}
})
然后在app.json中配置
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
demo展示
搜索