准备工作
所用到的技术
- 腾讯地图微信小程序SDK
- 高德地图WebServiceAPI服务
- APP获取是否授权插件
- uview框架(不是必须)
接下来带大家去申请
腾讯地图微信小程序SDK
微信小程序JavaScript SDK
点击下载 JavaScriptSDK v1.2
然后去申请腾讯地图的 key
先创建应用 > 在添加key
在应用列表中就能看到我们申请的 key 了
高德地图WebServiceAPI服务
高德地图开放平台
高德地图这里只需要去申请一个 WebServiceAPI 服务的key
申请流程和腾讯地图一样
先创建应用 > 在添加key
APP获取是否授权插件
在 dcloud 插件市场添加 插件链接
直接使用 HBuilderX 导入到项目
选择自己的项目即可
uview框架
uview 框架这里就不写操作步骤了
大家根据步骤安装就行了
代码实现
两个页面 index.vue fixedPosition.vue
首页index.vue代码
<template>
<view class="content">
<button class="" @click="positionClick">点击选择位置</button>
<view class="">当前地址:{{address.city}}{{address.area}}</view>
<view class="">当前位置坐标:{{address.lng}},{{address.lat}}</view>
</view>
</template>
<script>
import QQMapWX from '@/utils/qqmap-wx-jssdk.min.js' // 腾讯地图SDK (自己把腾讯地图SDK添加到自己指定的文件)
export default {
data() {
return {
address: {
city: '',// 城市
area: '',// 区、县
lng: '',// 经度
lat: '' // 纬度
}
}
},
onLoad() {
// 位置授权
this.getLocation()
},
onShow() {
let _this = this
// 重新获取定位
uni.$on('againLocation', function() {
_this.address = {
city: '',
area: '',
lng: '',
lat: ''
}
_this.getLocation()
})
// 解析传过来的位置
uni.$on('getLocation', function(city, area) {
let address = city + area
_this.getMapAddress(address)
})
},
mounted() {
},
methods: {
// 选择位置
positionClick() {
let item = encodeURIComponent(JSON.stringify(this.address))
uni.navigateTo({
url: `/pages/fixedPosition/index?item=${item}`
})
},
// 重新获取定位
getLocation() {
let _this = this
uni.getLocation({
type: 'wgs84',
success: function(res) {
_this.getAddress(res.longitude, res.latitude).then(res => {
_this.address = {
city: res.result.ad_info.city,
area: res.result.ad_info.district,
lng: res.result.ad_info.location.lng,
lat: res.result.ad_info.location.lat
}
}).catch(res => {})
},
fail() {
// 首次拒绝授权位置(根据自己要求配置或不配默认地址)
_this.address = {
city: '北京市',
area: '',
lng: '116.407526',
lat: '39.904030'
}
}
});
},
// 高德位置解析
getMapAddress(address) {
let _this = this
return new Promise(function(resolve, reject) {
uni.request({
url: `https://restapi.amap.com/v3/geocode/geo?address=${ address }&key=这里填高德申请的key`,
method: "GET",
success(res) {
console.info("高德地图", res)
if (res.data.status == 1) {
const coordinate = res.data.geocodes[0].location.split(",")
_this.address = {
city: res.data.geocodes[0].city,
area: res.data.geocodes[0].district.length != 0 ? res.data.geocodes[0].district : "",
lng: coordinate[0],
lat: coordinate[1],
}
}
resolve();
},
});
});
},
// 腾讯地图经纬度转中文地址
getAddress(lng, lat) {
return new Promise((resove, reject) => {
const qqmapsdk = new QQMapWX({
key: '腾讯地图申请的key', //之前在腾讯位置服务申请的key
})
qqmapsdk.reverseGeocoder({
location: {
latitude: lat,
longitude: lng,
},
success: (res) => {
resove(res)
},
fail: (e) => {
reject(e)
},
})
})
}
}
}
</script>
<style lang="scss" scoped>
.content {}
</style>
城市列表fixedPosition.vue页面
<template>
<view class="fixed-position">
<!-- 城市搜索 -->
<view class="search">
<input placeholder="请输入城市" border="surround" v-model="code" shape="circle" prefixIcon="search" clearable
@focus="inputFocus" @blur="inputBlur" @input="inputFun"></input>
<view class="cancel" v-show="isCancel" @click="inputCancel">取消</view>
</view>
<!-- 搜索结果模块 -->
<view class="search-box" v-show="isFocus || isCancel">
<view class="search-item" v-for="(item,index) in searchList" :key="index" @click="getLocation(item.name)">
<view class="">{{item.name}}</view>
</view>
</view>
<!-- 城市、区县切换tabs 就这里用到了uview框架 -->
<u-tabs :list="tabsList" :current="current" @click="tabsClick" v-show="!isCancel"></u-tabs>
<view v-show="current == 0">
<!-- 当前位置、重新定位功能 -->
<view class="current-location" v-show="!isCancel">
<view class="left">当前:{{area.city}}{{area.area}}</view>
<view class="right" @click="Repositioning"><u-icon name="map" style="margin-right: 10rpx;"></u-icon>重新定位
</view>
</view>
<!-- 右侧索引 -->
<view class='letter_right' v-show="!isCancel">
<text class='letter_item' v-for='(item,index) in letter' :key='index'
@tap.stop='letterTap(index)'>{{item}}</text>
</view>
<!-- 城市列表 -->
<scroll-view scroll-with-animation="true" class="cityListView" scroll-y="true" :scroll-into-view="scrollId"
v-show="!isCancel">
<view class="city-index-list">
<view class="city-item" v-for="(item,index) in cityList" :key="index" :id="item.letter">
<view class="letter">{{item.letter}}</view>
<view class="city" v-for="(text) in item.city" @click="getLocation(text.name)">{{text.name}}</view>
</view>
</view>
</scroll-view>
</view>
<!-- 区县展示 -->
<view class="area" v-show="current == 1">
<view class="area-list">
<view class="area-item" v-for="(item,index) in areaList" :key="index">
<view class="area-title" @click="areaLocation(item.name)">{{item.name}}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { city } from './city.js' // 结尾有下载地址
import { area } from './area.js' // 结尾有下载地址
import permision from "@/js_sdk/wa-permission/permission.js" // 导入从DCloud安装的插件
export default {
data() {
return {
address: {
city: '',
cityId: ''
},
code: '',
scrollId: '',
letter: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T","U", "V", "W", "X", "Y", "Z"],
cityList: city,
cityAll: [],
tabsList: [{name: '国内'}, {name: ''}],
areaList: [],
areaAll: [],
searchList: [],
current: 0,
area: {
city: '',
area: ''
},
isFocus: false,
isCancel: false
}
},
onLoad(options) {
// 首页传过来的数据
let item = JSON.parse(decodeURIComponent(options.item))
let name = item.city.split("市").join("");
this.cityList.forEach(itemS => {
itemS.city.forEach(text => {
if (text.name === item.city) {
this.address.city = text.name
this.address.cityId = text.id
}
})
})
// 根据城市ID查找出改城市所属的区县
this.areaList = area[this.address.cityId]
this.area.city = item.city
this.area.area = item.area
// 初始tabs标题
this.tabsList[1].name = name + '区县'
},
async onShow() {
let isLocations = false
let _this = this
let device = uni.getSystemInfoSync().platform // 获取当前设备
if (device === 'android') {
isLocations = await permision.requestAndroidPermission("android.permission.ACCESS_FINE_LOCATION") // 安卓方法返回用户是否授权获取位置
} else if (device === 'ios') {
isLocations = permision.judgeIosPermission("location") // ios方法返回用户是否授权获取位置
} else {
isLocations = await this.weChatGetLocation() // 返回微信小程序是否授权了位置
}
// 未授权时弹窗提示用户授权
if (!isLocations) {
uni.showModal({
title: '提示',
content: '请开启位置信息权限',
showCancel: false,
success() {
// 设备为android或ios是跳转系统设置(用户自行设置)
if (device === 'android' || device === 'ios') {
permision.gotoAppPermissionSetting(); // 打开权限设置界面
uni.navigateBack()
} else {
// 微信小程序时打开小程序设置界面
uni.openSetting({
success: (res) => {}
})
}
}
});
}
},
mounted() {
// 初始化城市JS数据
this.cityList.forEach(item => {
this.cityAll = this.cityAll.concat(item.city)
})
},
onUnload() {
// 销毁事件监听
uni.$off('againLocation')
uni.$off('getLocation')
},
methods: {
// 重新定位
Repositioning() {
uni.$emit('againLocation')
uni.navigateBack()
},
// 获取定位
getLocation(item) {
let name = item
uni.$emit('getLocation', name)
uni.navigateBack()
},
// 区定位
areaLocation(item) {
uni.$emit('getLocation', this.area.city, item)
uni.navigateBack()
},
// 右边索引点击
letterTap(index) {
this.scrollId = this.letter[index]
},
// tabs状态切换
tabsClick(item) {
this.current = item.index
},
// 搜索输入框聚焦
inputFocus() {
this.isFocus = true
this.isCancel = true
},
// 搜索输入框失去焦点
inputBlur() {
this.isFocus = false
},
// 搜索框取消
inputCancel() {
this.isCancel = false
},
// 搜索输入框输入事件
inputFun(e) {
let value = e
let newArray = []
if (value == '') {
this.searchList = []
} else {
for (let i = 0; i < this.cityAll.length; i++) {
if (this.cityAll[i].name.indexOf(value) != -1 || this.cityAll[i].letter == value.toUpperCase()) {
newArray.push(this.cityAll[i])
}
}
this.searchList = newArray
}
},
// 微信小程序是否授权位置信息
weChatGetLocation() {
return new Promise((resolve, reject) => {
uni.authorize({
scope: 'scope.userLocation',
success() {
resolve(true)
console.log('授权了')
},
fail() {
resolve(false)
console.log('没有授权')
}
})
})
}
}
}
</script>
<style lang="scss" scoped>
.fixed-position {
background-color: #fff;
.search {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
padding-bottom: 0rpx;
.cancel {
margin-left: 30rpx;
}
}
.search-box {
width: 100vw;
height: calc(100vh - 96rpx);
.search-item {
height: 88rpx;
line-height: 88rpx;
padding-left: 30rpx;
border-bottom: 1rpx solid #eee;
display: flex;
align-items: center;
}
}
.current-location {
padding: 30rpx 30rpx;
background-color: #fff;
display: flex;
justify-content: space-between;
.right {
display: flex;
align-items: center;
::v-deep .u-icon--right {
margin-right: 10rpx;
}
}
}
.letter_right {
z-index: 99;
width: 60rpx;
display: flex;
height: 100%;
position: fixed;
right: 0;
flex-direction: column;
justify-content: center;
top: 60rpx;
.letter_item {
display: block;
font-size: 20rpx;
color: #666;
text-align: center;
padding-left: 20rpx;
padding-top: 3rpx;
padding-bottom: 3rpx;
font-weight: bold;
}
}
.cityListView {
height: calc(100vh - 284rpx);
.city-index-list {
.city-item {
.letter {
height: 88rpx;
line-height: 88rpx;
font-weight: bold;
border-bottom: 1rpx solid #eee;
padding-left: 30rpx;
}
.city {
height: 88rpx;
line-height: 88rpx;
padding-left: 30rpx;
border-bottom: 1rpx solid #eee;
}
}
}
}
.area {
.area-list {
display: flex;
flex-wrap: wrap;
padding: 30rpx;
.area-item {
width: 33%;
height: 110rpx;
text-align: center;
.area-title {
width: 70%;
margin: 0 auto;
height: 68rpx;
line-height: 68rpx;
border: 1rpx solid #eee;
background: #fff;
border-radius: 10rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
padding: 0 20rpx;
}
}
}
}
}
</style>
注意(必看)
APP:如果你的APP时在开发阶段需要打开 定位功能
在项目的 manifest.json 中的 APP模块配置
有问题可以留言也可以私我。
到这里也就结束了,谢谢大家观看。