系列文章目录
通过高德地图坐标转换接口,完成微信wx.getLocation()jsdk坐标转换,实现定位高精确度效果
前言
一起开始在百度找了坐标转换,腾讯地图转换成百度地图坐标等等方法但是误差还是很多很难搞,后来看高德原生的地图api里面有浏览器精确定位,我就想着搬到微信公众号,但是公司比较穷,用不起https,没办法,只能试试高德坐标转换api希望误差不要太大,结果还是很好的
一、下载高德
//建议用yarn速度快
npm install vue-amap --save
yarn add vue-amap
//main.js
AmapVue.config.version = '2.0'; // 默认2.0,这里可以不修改
AmapVue.config.key = 'xx';
AmapVue.config.plugins = [
'AMap.ToolBar',
'AMap.MoveAnimation',
'AMap.AutoComplete',
'AMap.PlaceSearch',
'AMap.Geocoder',
'AMap.Geolocation'
// 在此配置你需要预加载的插件,如果不配置,在使用到的时候会自动异步加载
];
代码如下(示例):
二、封装地图组件,vantUI
代码如下(示例):
<template>
<div>
<van-popup width="600"
:style="{ height: '100%',width:'100%' }"
v-model="open"
>
<van-cell style="margin-top:10px;padding: 0px">
<van-row type="flex" justify="space-between">
<van-col span="12"><van-button plain hairline type="primary" @click="closeAlertDialog">取消</van-button></van-col>
<van-col span="12" style="text-align: end" > <van-button plain hairline type="primary" @click="OKAlertDialog">确定</van-button></van-col>
</van-row>
当前已选中地点:{{addressName}}
<van-search class="page-select-lump" v-model="keyword" placeholder="请输入搜索关键词" :show-action="keyword !== ''"
@cancel="onCancel">
<template v-if="loading" #left-icon>
<van-loading size="24"/>
</template>
</van-search>
</van-cell>
<mu-button slot="left" icon @click="closeAlertDialog">
<mu-icon value="close"></mu-icon>
</mu-button>
<amap
ref="myMap"
:style="{height:'80vh'}"
cache-key="coord-picker-map"
async
:center.sync="center"
:zoom.sync="zoom"
is-hotspot
map-style="amap://styles/makaron"
@click="onMapClick"
>
<amap-satellite-layer :visible="satellite"/>
<amap-marker v-if="position" ref="mapMarker" :position.sync="position"
:label="{
content: SearchAddress.formattedAddress,
direction: 'bottom',
}"/>
<div class="operation" style="margin-bottom: 20px;">
<div class="operation-box" @click="addressPositon()">
<van-icon name="location"/>
<p>定位</p>
</div>
</div>
</amap>
<van-popup v-model="searchH" position="bottom" :overlay="false" closeable :style="{ height: '30%' }">
<van-list
v-if="list.length > 0"
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<van-cell v-for="item in list" :key="item.id" :title="item.name" :label="item.address" @click="goMap(item)"/>
</van-list>
<div class="noAd" v-else>
搜索不到地址,请重新输入
</div>
</van-popup>
</van-popup>
<div class="operation" style="margin-bottom: 20px;">
<div class="operation-box" @click="()=>{open=true}">
<van-icon name="location"/>
<p>定位</p>
</div>
</div>
</div>
</template>
<script>
import DragRise from '@/components/action/drag-rise' // 拖拽升起组件
import {loadPlugins} from '@amap/amap-vue';
import axios from 'axios'
export default {
name: "AddressAmap",
components: {DragRise},
props: {
open: {
default: false
},
TypeData: {
type: Array,
default: function () {
return []
}
},
},
data() {
return {
map: null,
value: null,
BMap: null, // 地图组件是否就绪 地图实例
h: window.innerHeight,
ak: "xxxx",
zoom: 14, // 画布大小
center: null, // 画布中心位置
location: "广东", // 搜索固定区域
keyword: "", // 搜索内容
SearchAddress: {address: "", point: null}, // 检索点详细信息
point: null, // 点击地图设置家或学校位置
nowAddress: {lng: 0, lat: 0}, // 当前定位位置
type: false,
address: {},
addlist: {},
addressName: '',
satellite: false,
position: null,
list: [],
loading: false,
finished: false,
searchH: false,
pageSize: 15,
pageIndex: 1,
searchState: false,
}
},
watch: {
// 检索点详细信息
keyword(newValue) {
// this.$refs.dragRise.shrink();
// let Hei = this.$refs.dragRise.Hei - 34;
// console.log('this.$refs.dragRise.dragRiseHei', this.$refs.dragRise.dragRiseHei);
let h = window.innerHeight * 2;
let _this = this;
let timer = null;
console.log(newValue, 'asss');
if (newValue === "") {
_this.searchH = false;
this.SearchAddress = {address: "", point: null};
} else {
this.searchAD(true);
_this.searchH = true;
}
},
async open(v) {
if (v == true) {
await loadPlugins(['AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.Geolocation']);
this.ps = new AMap.PlaceSearch({
pageSize: this.pageSize,
city: '全国',
citylimit: true,
});
this.ac = new AMap.AutoComplete()
var options = {
'showButton': false,//是否显示定位按钮
'buttonPosition': 'LB',//定位按钮的位置
/* LT LB RT RB */
'buttonOffset': new AMap.Pixel(10, 20),//定位按钮距离对应角落的距离
'showMarker': true,//是否显示定位点
'markerOptions':{//自定义定位点样式,同Marker的Options
'offset': new AMap.Pixel(-18, -36),
'content':'<img src="https://a.amap.com/jsapi_demos/static/resource/img/user.png" style="width:36px;height:36px"/>'
},
'showCircle': true,//是否显示定位精度圈
'circleOptions': {//定位精度圈的样式
'strokeColor': '#0093FF',
'noSelect': true,
'strokeOpacity': 0.5,
'strokeWeight': 1,
'fillColor': '#02B0FF',
'fillOpacity': 0.25
}
}
this.geocoder = new AMap.Geocoder(options)
console.log(this.$refs.myMap,'this.$refs.myMapthis.$refs.myMap');
this.addressPositon()
// this.WXlocation()
console.log('geocoder', )
}
}
},
mounted() {
axios.get()
this.$nextTick(() => {
this.$refs.dragRise.load() // 初始化组件
this.mapcontent()
})
},
methods: {
//定位
addressPositon() {
var _this = this
_this.wx.error(function (res) {
console.log(res, '错误')
})
_this.wx.ready(function () {
_this.wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: function (res) {
console.log(res,'111');
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
// _this.form.coordinateLeft = latitude
// _this.form.coordinateRight =longitude
//_this.form.address=latitude+'-'+longitude
console.log( longitude,latitude, '定位11111')
var addegt=[]
addegt.push(longitude)
addegt.push(latitude)
axios.get('https://restapi.amap.com/v3/assistant/coordinate/convert',{
params: {
key:'xxxx',
coordsys:'gps',
locations:addegt.join(','),
}
}).then(res => {
console.log(res,res.data.locations,'sad');
var address=res.data.locations.split(',')
if (res.data.status == 1) {
var lat =address[1] // 纬度,浮点数,范围为90 ~ -90
var lng = address[0]// 经度,浮点数,范围为180 ~ -180。
_this.position=[lng,lat]
console.log(_this.position,'_this.position=_this.position=');
// this.position=[114.0705726454,22.71638671875]
_this.center = [lng,lat];
_this.getAddress(_this.position)
}
// console.log(JSON.parse(res.msg),data)
})
// _this.wx.openLocation({
// latitude: parseFloat(latitude), // 纬度,浮点数,范围为90 ~ -90
// longitude: parseFloat(longitude), // 经度,浮点数,范围为180 ~ -180。
// name: 'a', // 位置名
// address: '', // 地址详情说明
// scale: 18, // 地图缩放级别,整型值,范围从1~28。默认为最大
// infoUrl: '', // 在查看位置界面底部显示的超链接,可点击跳转
// success: function (res) {
// console.log(res,'asas')
// }
// });
}
});
// _this.$toast('定位')
})
},
WXlocation() {
console.log('点击定位')
var options = {
noIpLocate:0,
noGeoLocation:0,
useNative:true,
'showButton': false,//是否显示定位按钮
'buttonPosition': 'LB',//定位按钮的位置
/* LT LB RT RB */
'buttonOffset': new AMap.Pixel(10, 20),//定位按钮距离对应角落的距离
'showMarker': true,//是否显示定位点
'markerOptions':{//自定义定位点样式,同Marker的Options
'offset': new AMap.Pixel(-18, -36),
'content':'<img src="https://a.amap.com/jsapi_demos/static/resource/img/user.png" style="width:36px;height:36px"/>'
},
'showCircle': true,//是否显示定位精度圈
'circleOptions': {//定位精度圈的样式
'strokeColor': '#0093FF',
'noSelect': true,
'strokeOpacity': 0.5,
'strokeWeight': 1,
'fillColor': '#02B0FF',
'fillOpacity': 0.25
}
}
// var geolocation = new AMap.Geolocation(options)
// this.$nextTick(()=>{
// var geolocation = new AMap.Geolocation(options);
// this.$refs.myMap.$map.addControl(geolocation);
// geolocation.getCurrentPosition((status,result)=>{
// if(status=='complete'){
// console.log(result,'aaaaa');
// this.position=[result.position.lng,result.position.lat]
// // this.position=[114.0705726454,22.71638671875]
// this.getAddress(this.position)
// }else{
//
// }
// });
// })
},
goMap(val) {
this.keyword = '';
this.center = [val.location.lng, val.location.lat];
this.position = [val.location.lng, val.location.lat];
this.getAddress(this.position);
},
onMapClick(e) {
if (e.lnglat) {
this.position = [e.lnglat.lng, e.lnglat.lat];
this.center = [e.lnglat.lng, e.lnglat.lat];
this.getAddress(this.position)
} else {
this.position = null;
}
},
mapcontent() {
},
onCancel() {
},
searchAD(state) {
console.log(state)
if (state) {
this.searchState = true;
// this.$refs.searchList.scrollTo(0, 0, true);
this.finished = false;
this.pageIndex = 1;
this.ps.setPageIndex(this.pageIndex);
this.ps.search(this.keyword, (status, result) => {
this.searchState = false;
this.loading = false;
console.log(status, result);
// this.searching = false;
// if (query !== this.query) return;
if (status === 'complete' && result.poiList) {
this.list = result.poiList.pois;
if (this.list.length < 15) {
this.finished = true
}
} else {
this.list = [];
this.finished = true
}
});
} else {
this.pageIndex += 1;
this.ps.setPageIndex(this.pageIndex);
this.ps.search(this.keyword, (status, result) => {
this.loading = false;
// this.searching = false;
// if (query !== this.query) return;
if (status === 'complete' && result.poiList) {
this.list = this.list.concat(result.poiList.pois);
console.log(status, result)
} else {
this.finished = true
// this.results = [];
// this.total = 0;
}
});
}
},
AddOrUpdate() {
},
onLoad() {
this.searchAD(false);
},
/**
* 根据经纬度获取位置信息
* @param position
*/
getAddress(position) {
console.log(position, 'position');
var this_ = this;
this.geocoder.getAddress(position, function(status, result) {
if (status === 'complete' && result.regeocode) {
this_.SearchAddress = result.regeocode;
this_.$refs.mapMarker.label = {
content: this_.SearchAddress.formattedAddress,
direction: 'bottom',
};
console.log('status', status);
console.log('result', result)
this_.addressName= this_.SearchAddress.formattedAddress
this_.addlist={poresultsition: position, result: result}
// this_.searchH=true
} else {
this_.SearchAddress = {
formattedAddress: '高德暂无此地址信息'
}
}
})
},
onSearch(v) {
//输入提示
var autoOptions = {
input: "tipinput"
};
var auto = new AMap.Autocomplete(autoOptions);
var placeSearch = new AMap.PlaceSearch({
map: this.map
}); //构造地点查询类
AMap.event.addListener(auto, "select", select);//注册监听,当选中某条记录时会触发
function select(e) {
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name); //关键字查询查询
}
},
closeAlertDialog(v) {
this.open=false
this.$emit('closeDialog', false)
},
OKAlertDialog(v) {
this.open=false
this.$emit('change',this.addlist)
},
SetADDoptions() {
},
}
}
</script>
<style scoped lang="less">
#panel {
position: absolute;
background-color: white;
max-height: 30%;
overflow-y: auto;
top: 10px;
right: 10px;
width: 280px;
}
.noAd {
color: silver;
text-align: center;
margin: 14px 0px;
}
.search-list {
z-index: 999;
position: fixed;
width: 100%;
overflow: auto;
bottom: 0;
background-color: white;
transition: 0.6s;
}
.AddreseSearch {
z-index: 2010;
position: fixed;
top: 0px;
width: 100%;
.van-search__content, .van-search__content--square {
background-color: #F6F6F6 !important;
}
.van-cell, .van-cell--borderless, .van-field {
background-color: #F6F6F6 !important;
}
}
// 搜索框
.btnMap {
padding-top: 6px;
overflow: hidden;
font-size: 12px;
button {
height: 35px;
line-height: 35px;
width: 95px;
}
button:nth-child(1) {
float: left;
margin-left: 10px;
}
button:nth-child(2) {
float: right;
margin-right: 10px;
}
}
// 修改保存按钮
.WatchAdderss_menu {
z-index: 99;
position: fixed;
bottom: 25px;
left: 10px;
div {
width: 40px;
height: 40px;
padding: 6px;
margin: 6px;
background-color: #8dc63f;
border-radius: 5px;
text-align: center;
p {
color: rgba(25, 31, 37, 0.56);
}
img {
margin-top: 3px;
width: 18px;
height: 18px;
}
}
}
.operation {
position: fixed;
bottom: 20px;
right: 20px;
border-radius: 10px;
box-shadow: 1px 2px 4px #bbbbbb;
// background-color: #fffdef;
.operation-box {
padding: 12px;
text-align: center;
font-size: 14px;
color: #707070;
}
}
// 菜单样式
</style>
三、拖拽组件,vantUI
代码如下(示例):
//DragRise
<template>
<div class="dragRiseHei" :style="{ top: '-' + dragRiseInitial + 'px', boxShadow: searchFig ? '0px 0px 2px #bbbbbb' : '' }" >
<div ref="dragRiseVal">
<!--<div class="interval-8 back-default"/>-->
<div class="dragRiseVal" :style="{ height: dragRiseVal !== 0 ? dragRiseVal+ 'px' : ''}">
<slot name="value"></slot>
</div>
</div>
<div ref="dragRiseInitial" style="overflow: hidden">
<div style="overflow: hidden">
<slot name="title"></slot>
</div>
<img class="dragRiseHei_img" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" :class="searchFig ? 'dragRiseHei_imgFZ' : ''"
src="require('@/assets/map/ic_sl.png')">
</div>
</div>
</template>
<script>
export default {
data () {
return{
Hei: 0, // 记录初始高度
clientY: 0, // 记录滑动距离
dragRiseInitial:0, // 初始高度、以及改变的高度
dragRiseVal: 0, // 内容高度
dragRiseHei: 0, // 组件高度
dragState: false,
searchFig: false, // 搜索升起或隐藏
}
},
created () {},
watch: {
clientY (val, oldVal) {
let H = this.dragRiseVal // 页面可视高度
if (oldVal !== 0 && this.dragRiseInitial <= H) {
let num = Math.abs(oldVal - val) > 50 ? 30 : oldVal - val
this.dragRiseInitial += num
if (this.dragRiseInitial < 0) { this.dragRiseInitial = 0 }
if (this.dragRiseInitial > H) { this.dragRiseInitial = H }
}
}
},
methods: {
open () {
this.searchFig = true
},
load () {
const THIS = this // 页面渲染比数据渲染快需要稍等一下
setTimeout(function () {
const Height = document.body.clientHeight // 页面可视高度
THIS.Hei = (THIS.$refs.dragRiseInitial.offsetHeight)
// THIS.dragRiseInitial = (THIS.$refs.dragRiseVal.offsetHeight)
THIS.dragRiseVal = THIS.$refs.dragRiseVal.offsetHeight
// console.log('wudi3', THIS.dragRiseVal)
// 组件高度等于初始高度 + 内容高度
THIS.dragRiseHei = THIS.dragRiseVal + THIS.Hei
console.log('dragRiseHei', THIS.dragRiseHei)
// 当组件高度大于页面高度时重新内容高度赋值
if (THIS.dragRiseHei > Height) {
THIS.dragRiseHei = Height // 组件高度
THIS.dragRiseVal = Height - THIS.dragRiseInitial // 得出内容高度
}
}, 200)
},
touchstart () {
},
touchmove (e) {
this.dragState = true
let H = this.dragRiseVal
if (this.dragRiseInitial - Math.ceil((H + 20) / 2) > 0) {this.searchFig = true } else { this.searchFig = false }
// 当拉起高度高于元素高度时禁止拉动
console.log(this.dragRiseInitial,this.dragRiseVal);
if (this.dragRiseInitial <= this.dragRiseVal) {
console.log('wudi2', H)
this.clientY = e.touches[0].clientY
} else {
this.dragRiseInitial = this.dragRiseVal
}
},
animation () {
let H = this.dragRiseVal;
let _this = this
let timer = null
timer = requestAnimationFrame(function fn () {
if (_this.searchFig) {
if (_this.dragRiseInitial < H) {
_this.dragRiseInitial += 20;
timer = requestAnimationFrame(fn)
} else {
_this.dragRiseInitial = H;
cancelAnimationFrame(timer)
}
} else {
console.log('fig', _this.dragRiseInitial, _this.Hei)
if (_this.dragRiseInitial > 0) {
_this.dragRiseInitial -= 20;
timer = requestAnimationFrame(fn)
} else {
_this.dragRiseInitial = 0;
cancelAnimationFrame(timer)
}
}
})
},
shrink() {
this.searchFig = true
this.animation()
},
touchend (fig) {
let H = this.dragRiseVal
let _this = this
if (this.dragState) {
if (fig) {
if (this.dragRiseInitial - Math.ceil((H + 20) / 2) > 0) { _this.searchFig = true } else { _this.searchFig = false }
} else { _this.searchFig = false }
} else {
this.searchFig = !this.searchFig
}
this.dragState = false
this.animation()
},
},
}
</script>
<style lang="less" scoped>
.dragRiseHei{
overflow: hidden;
position: fixed;
top: 0px;
width: 100%;
border-radius: 0px 0px 10px 10px;
background-color: red;
.dragRiseHei_img{
display: block;
margin: 0 auto;
padding: 12px 120px;
position: relative;
width: 40px;
height: 12px;
}
.dragRiseHei_imgFZ {
transform:rotate(180deg);
-ms-transform:rotate(180deg); /* Internet Explorer */
-moz-transform:rotate(180deg); /* Firefox */
-webkit-transform:rotate(180deg); /* Safari 和 Chrome */
-o-transform:rotate(180deg); /* Opera */
} /* 水平镜像翻转 */
.dragRiseVal{
overflow:auto;
}
}
</style>