更新记录
2.0.0(2021-01-04) 下载此版本
- 使用jsonp方式代替代理设置。解决了跨域问题也更方便插件的使用。
插件使用步骤:
1. 申请腾讯地图mapKey
- 打开腾讯位置服务系统,登录/注册账号->右上角进入控制台-> key管理。
- 设置合法域名或IP。【应用产品】设置为WebServiceAPI,配置即将引入该组件的网站域名或ip,其他保存默认设置,单击【保存】。
2. 使用插件
-
引入腾讯APIjs文件。在vue项目的index.html中引入,其中key需换成第一步申请到的key。
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=JDKBZ-****"></script>
-
替换mapKey,WellTencentMap.vue中的mapKey需换上面申请到的key。
data() {
return {
mapKey: 'JDKBZ-****',
};
},
- 使用组件。(此处我的组件名为well-tencent-map)
<well-tencent-map :selectedValue="selectedValue" @selected-change="mapSelectedChange"></well-tencent-map>
- 参数:
selectedValue:可不传、可传null、支持异步获取回来的数据。若传入,格式如下: { location: { lat: null, lng: null, }, address: null, province: null, city: null, district: null }
- 事件:
selected-change:当标记的点发生变化时,触发。
该插件实现的功能:
- 外部传入经纬度,地图上显示标记。
- 根据关键词搜索地址。
- 点击地图,标记点,并显示经纬度、地址详细信息。
- 点击搜索结果的某一项,地图上显示标记。
- 效果图:
1.0.0(2020-12-29) 下载此版本
背景
百度地图插件vue-baidu-map拾取的经纬度在小程序上显示时存在偏差。
小程序使用的是腾讯自家的地图。两个地图用的是两套坐标系,腾讯地图、高德地图用的是GCJ-02坐标,也就是国测局坐标系,而百度是自成一套,BD-09坐标系,所以相同地点在经纬度在两个坐标系是不一样的,或者说有偏移。
解决方案如下:
对于后台百度地图传过来的经纬度,要做一次转换,转换成腾讯地图的经纬度,再传给小程序显示。
function convert2TecentMap(lng, lat) {
if (lng == '' && lat == '') {
return {
lng: '',
lat: ''
}
}
var x_pi = 3.14159265358979324 * 3000.0 / 180.0
var x = lng - 0.0065
var y = lat - 0.006
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi)
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi)
var qqlng = z * Math.cos(theta)
var qqlat = z * Math.sin(theta)
return {
lng: qqlng,
lat: qqlat
}
}
由于不想做转换,所以基于腾讯地图封装了个vue组件。
- 实现的功能:
- 外部传入经纬度,地图上显示标记。
- 根据关键词搜索地址。
- 点击地图,标记点,并显示经纬度、地址详细信息。
- 点击搜索结果的某一项,地图上显示标记。
- 效果图:
组件的使用
1. 申请mapKey
- 打开腾讯位置服务系统,登录/注册账号->右上角进入控制台-> key管理。
- 设置合法域名或IP。这一步很重要,否则后续的逆向解析将会提示
“域名/ip未授权”
。【应用产品】设置为WebServiceAPI,配置即将引入该组件的网站域名或ip,其他保存默认设置,单击【保存】。
2. 内部实现逻辑
- mapKey:需换成您上一步申请到的key。
<template>
<div class="well-map">
<div class="selected-info">
<div>
<span class="label">经度:</span>
<span>{{selfSelectedValue.location.lng}}</span>
</div>
<div>
<span class="label">纬度:</span>
<span>{{selfSelectedValue.location.lat}}</span>
</div>
<div>
<span class="label">地址:</span>
<span>{{selfSelectedValue.address}}</span>
</div>
</div>
<div class="search-row" v-clickoutside="handleBlur">
<div class="input-wrap">
<input type="text" v-model="searchKey" @input="handleSearch()" @click="handleFoucus" placeholder="请输入要搜索的地址"/>
<button type="button" @click="handleSearch()">搜索</button>
</div>
<ul v-show="showAddressList && addressList.length">
<li v-for="(item,index) in addressList" :key="index" @click.stop="handleSelect(item)">
<span class="title">{{item.title}}</span>
<span class="other-info">{{item.address}}</span>
</li>
</ul>
</div>
<div id="well-container" class="well-map-container"></div>
</div>
</template>
<script>
/**
* 使用:<well-tencent-map :selectedValue="selectedValue" @selected-change="mapSelectedChange"></well-tencent-map>
* 参数:
* 1. selectedValue:可不传、可传null、支持异步数据。若传入,格式如下:
* {
* location: {
* lat: null,
* lng: null,
* },
* address: null,
* province: null,
* city: null,
* district: null
* }
* 函数:
* 1. selected-change:当选中的点发生变化时,触发
* **/
import axios from 'axios';
export default {
props: {
selectedValue: {
type: Object,
required: false
}
},
data() {
return {
timeout: null, //搜索防抖
selfSelectedValue: {
location: {
lat: null,
lng: null,
},
address: null,
province: null,
city: null,
district: null
},
searchKey: '',//搜索Key
addressList: [],//搜索结果
mapKey: 'JDKBZ-****',//腾讯地图mapKey,需到https://lbs.qq.com/上申请
map: null,
markerLayer: null,
showAddressList: false
};
},
mounted() {
//初始化地图
this.initMap();
},
watch: {
selectedValue: {
handler(newValue, oldName) {
let value = newValue || {};
let _newLoca = value.location || {};
let _oldLoca = this.selfSelectedValue.location || {};
let mergeResult = {
location: {
lat: _newLoca.lat,
lng: _newLoca.lng,
},
address: value.address,
province: value.province,
city: value.city,
district: value.district,
};
//判断经纬度是否发生变化,如果变化,则需要重新画点
if (_oldLoca.lat !== _newLoca.lat || _oldLoca.lng !== _newLoca.lng) {
if (this.map && this.markerLayer) {
//1. 地图如果渲染完了,则把画点画上去
//2. 如果没有渲染完,也无需担心,在init会根据selfSelectedValue的最新值绘制
this._drawPoint(_newLoca.lat, _newLoca.lng, true);
}
}
this.selfSelectedValue = mergeResult;
},
immediate: true
}
},
directives: {
/**
* 封装指令,监听点击非目标元素之外的dom
* ***/
clickoutside: {
bind(el, binding, vnode) {
function documentHandler(e) {
console.log('documentHandler');
// 这里判断点击的元素是否是本身,是本身,则返回
if (el.contains(e.target)) {
console.log('el.contains(e.target)');
return false;
}
// 判断指令中是否绑定了函数
if (binding.expression) {
// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
binding.value(e);
}
}
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler;
document.addEventListener('click', documentHandler);
},
update() {
},
unbind(el, binding) {
// 解除事件监听
document.removeEventListener('click', el.__vueClickOutside__);
delete el.__vueClickOutside__;
}
}
},
methods: {
/**
* 初始化地图
* **/
initMap() {
//初始化地图
this.map = new TMap.Map('well-container', {
rotation: 20, //设置地图旋转角度
pitch: 0, //设置俯仰角度(0~45)
zoom: 16, //设置地图缩放级别
});
//初始化marker图层
this.markerLayer = new TMap.MultiMarker({
id: 'marker-layer',
map: this.map
});
//监听点击事件添加marker
this.map.on('click', this._clickMap);
//初始化点(在_drawPoint中,做了经纬度是否存在的判断)
let location = this.selfSelectedValue.location || {};
this._drawPoint(location.lat, location.lng, true);
},
/**
* 搜索框聚焦
* **/
handleFoucus(e) {
console.log('handleFoucus');
this.showAddressList = true;
},
/**
* 搜索框失焦
* **/
handleBlur() {
console.log('handleBlur');
this.showAddressList = false;
},
/**
* 搜索框内容发生变化
* timeout是为了防抖
* **/
handleSearch() {
this.showAddressList = true;
console.log('handleSearch');
clearTimeout(this.timeout);
if (!this.searchKey) {
this.addressList = [];
} else {
this.timeout = setTimeout(() => {
axios({
url: `/wellTencentMap/ws/place/v1/suggestion?keyword=${this.searchKey}&key=${this.mapKey}`,
method: 'GET'
}).then(res => {
this.addressList = (res.data && res.data.data) || [];
}).catch(err => {
console.log(err);
});
}, 300);
}
},
/**
* 选中搜索列表中的某一项,row格式如下:
* {
* "id":"1594670327289385140",
* "title":"人才好娃幼儿园",
* "address":"辽宁省铁岭市银州区三眼井巷1",
* "category":"教育学校:幼儿园",
* "type":0,
* "location":{
* "lat":42.292420809,
* "lng":123.857382405
* },
* "adcode":211202,
* "province":"辽宁省",
* "city":"铁岭市",
* "district":"银州区"
* }* **/
handleSelect(row) {
console.log(JSON.stringify(row));
this.searchKey = row.title;
//searchKey发生变化了,需触发搜索
this.handleSearch();
let value = {
location: row.location,
address: row.address,
province: row.province,
city: row.city,
district: row.district
};
this.selfSelectedValue = value;
this._notifyParent(value);
//selectedValue发生变化了,需重新绘制点
this._drawPoint(row.location.lat, row.location.lng, true);
//选中之后需触发失去焦点
this.handleBlur();
},
/**
* 根据经纬度在地图上标注
* @param lat 纬度
* @param lng 经度
* @param isUpdateCenter 是否更新地图中心点,有以下三种情况:
* 1. 外部传入的点信息发生变化时,需更新中心点
* 2. 选中搜索列表的某一项时,需更新中心点
* 3. 点击地图标记点时,不需要更新中心点
* **/
_drawPoint(lat, lng, isUpdateCenter) {
//先清空点
this.markerLayer.setGeometries([]);
if (!lat || !lng) {
return;
}
//更新地图中心位置
if (isUpdateCenter) {
this.map.setCenter(
new TMap.LatLng(lat, lng)
);
}
this.markerLayer.add({
position: new TMap.LatLng(lat, lng)
});
},
/**
* 通知父组件,标记的点发生了变化
* **/
_notifyParent(value) {
// this.$emit('update:value', selectedValue);
// this.$emit('update:selectedValue', selectedValue);
this.$emit('selected-change', value);
},
/**
* 点击地图
* 1. 根据经纬度画点
* 2, 根据经纬度逆向查询到地址详细信息
* 3. 通知父组件
* **/
_clickMap(evt){
console.log('点击地图:', evt);
this._drawPoint(evt.latLng.lat, evt.latLng.lng, false);
let locationParam = evt.latLng.lat + ',' + evt.latLng.lng;
axios({
url: '/wellTencentMap/ws/geocoder/v1/?location=' + locationParam + '&key=' + this.mapKey + '&get_poi=0',
method: 'GET'
}).then(res => {
console.log('【' + locationParam + '】逆地址解析结果:', res);
let result = (res.data && res.data.result);
if (!result) {
// this.$message.error(res.data.message);
alert(res.data.message);
return;
}
let ad_info = result.ad_info || {};
let value = {
location: result.location,
address: result.address,
province: ad_info.province,
city: ad_info.city,
district: ad_info.district
};
this.selfSelectedValue = value;
this._notifyParent(value);
}).catch(err => {
console.log('逆地址解析失败', err);
});
},
}
};
</script>
<style lang="less" scoped>
.well-map {
/*position: relative;*/
line-height: normal;
.search-row {
position: relative;
/*line-height: normal;*/
width: 100%;
margin: 12px 0 4px 0;
/*left: 20px;*/
/*top: 20px;*/
z-index: 99009;
.input-wrap {
height: 32px;
line-height: 32px;
display: flex;
> input {
box-sizing: border-box;
margin: 0;
position: relative;
width: 100%;
height: 100%;
padding: 4px 11px;
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
background-color: #fff;
/*background-image: none;*/
border: 1px solid #d9d9d9;
border-radius: 4px 0 0 4px;
transition: all 0.3s;
border-right: none;
&:hover {
border-color: #40a9ff;
border-right-width: 1px !important;
}
&:focus {
border-color: #40a9ff;
border-right-width: 1px !important;
outline: 0;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
}
> button {
padding: 0 15px;
border-radius: 0 4px 4px 0;
color: #fff;
background: #1890ff;
border-color: #1890ff;
box-shadow: none;
border: none;
width: 82px;
height: 100%;
cursor: pointer;
&:hover, &:focus {
color: #fff;
background: #40a9ff;
border-color: #40a9ff;
outline: none;
}
&:active {
color: #fff;
background: #096dd9;
border-color: #096dd9;
outline: none;
}
}
}
> ul {
position: absolute;
top: 100%;
left: 0;
width: 100%;
background: rgba(252, 250, 250, 0.918);
border: 1px solid #f1f1f1;
font-size: 13px;
color: #5a5a5a;
max-height: 280px;
overflow-y: auto;
list-style: none;
padding: 0;
margin: 0;
> li {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: 100%;
border-bottom: 1px solid #f1f1f1;
padding: 10px;
margin: 0;
cursor: pointer;
&:hover {
background: #eff6fd;
}
.title {
display: block;
line-height: normal;
margin-bottom: 4px;
}
.other-info {
font-size: 12px;
color: #b9b9b9;
display: block;
line-height: normal;
}
}
}
}
.well-map-container {
width: 100%;
height: 300px;
}
.selected-info {
background: #ecf5ff;
padding: 10px 14px;
color: #565656;
font-size: 13px;
> div {
margin-bottom: 4px;
.label {
color: #757575;
}
&:last-child {
margin-bottom: 0;
}
}
}
}
</style>
3. 使用
- 引入腾讯APIjs文件。在vue项目的index.html中引入,其中key需换成第一步申请到的key。
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=JDKBZ-****"></script>
- 设置代理。在vue.config.js文件中,添加配置。
devServer: {
proxy: {
"/wellTencentMap": {
target: "https://apis.map.qq.com",
changeOrigin: true,
ws: true,
pathRewrite: {
'^/wellTencentMap': '' //重写接口
}
},
}
}
- 替换mapKey,组件实现逻辑中的mapKey需换上面申请到的key。
data() {
return {
mapKey: 'JDKBZ-****',
};
},
- 使用组件。(此处我的组件名为well-tencent-map)
<well-tencent-map :selectedValue="selectedValue" @selected-change="mapSelectedChange"></well-tencent-map>
- 参数:
selectedValue:可不传、可传null、支持异步获取回来的数据。若传入,格式如下: { location: { lat: null, lng: null, }, address: null, province: null, city: null, district: null }
- 事件:
selected-change:当标记的点发生变化时,触发。
平台兼容性
背景
百度地图插件vue-baidu-map拾取的经纬度在小程序上显示时存在偏差。
小程序使用的是腾讯自家的地图。两个地图用的是两套坐标系,腾讯地图、高德地图用的是GCJ-02坐标,也就是国测局坐标系,而百度是自成一套,BD-09坐标系,所以相同地点在经纬度在两个坐标系是不一样的,或者说有偏移。
解决方案如下:
对于后台百度地图传过来的经纬度,要做一次转换,转换成腾讯地图的经纬度,再传给小程序显示。
function convert2TecentMap(lng, lat) {
if (lng == '' && lat == '') {
return {
lng: '',
lat: ''
}
}
var x_pi = 3.14159265358979324 * 3000.0 / 180.0
var x = lng - 0.0065
var y = lat - 0.006
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi)
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi)
var qqlng = z * Math.cos(theta)
var qqlat = z * Math.sin(theta)
return {
lng: qqlng,
lat: qqlat
}
}
由于不想做转换,所以基于腾讯地图封装了个vue组件。
- 实现的功能:
- 外部传入经纬度,地图上显示标记。
- 根据关键词搜索地址。
- 点击地图,标记点,并显示经纬度、地址详细信息。
- 点击搜索结果的某一项,地图上显示标记。
- 效果图:
组件的使用
1. 申请mapKey
- 打开腾讯位置服务系统,登录/注册账号->右上角进入控制台-> key管理。
- 设置合法域名或IP。这一步很重要,否则后续的逆向解析将会提示
“域名/ip未授权”
。【应用产品】设置为WebServiceAPI,配置即将引入该组件的网站域名或ip,其他保存默认设置,单击【保存】。
2. 内部实现逻辑
- mapKey:需换成您上一步申请到的key。
<template>
<div class="well-map">
<div class="selected-info">
<div>
<span class="label">经度:</span>
<span>{{selfSelectedValue.location.lng}}</span>
</div>
<div>
<span class="label">纬度:</span>
<span>{{selfSelectedValue.location.lat}}</span>
</div>
<div>
<span class="label">地址:</span>
<span>{{selfSelectedValue.address}}</span>
</div>
</div>
<div class="search-row" v-clickoutside="handleBlur">
<div class="input-wrap">
<input type="text" v-model="searchKey" @input="handleSearch()" @click="handleFoucus" placeholder="请输入要搜索的地址"/>
<button type="button" @click="handleSearch()">搜索</button>
</div>
<ul v-show="showAddressList && addressList.length">
<li v-for="(item,index) in addressList" :key="index" @click.stop="handleSelect(item)">
<span class="title">{{item.title}}</span>
<span class="other-info">{{item.address}}</span>
</li>
</ul>
</div>
<div id="well-container" class="well-map-container"></div>
</div>
</template>
<script>
/**
* 使用:<well-tencent-map :selectedValue="selectedValue" @selected-change="mapSelectedChange"></well-tencent-map>
* 参数:
* 1. selectedValue:可不传、可传null、支持异步数据。若传入,格式如下:
* {
* location: {
* lat: null,
* lng: null,
* },
* address: null,
* province: null,
* city: null,
* district: null
* }
* 函数:
* 1. selected-change:当选中的点发生变化时,触发
* **/
import axios from 'axios';
export default {
props: {
selectedValue: {
type: Object,
required: false
}
},
data() {
return {
timeout: null, //搜索防抖
selfSelectedValue: {
location: {
lat: null,
lng: null,
},
address: null,
province: null,
city: null,
district: null
},
searchKey: '',//搜索Key
addressList: [],//搜索结果
mapKey: 'JDKBZ-****',//腾讯地图mapKey,需到https://lbs.qq.com/上申请
map: null,
markerLayer: null,
showAddressList: false
};
},
mounted() {
//初始化地图
this.initMap();
},
watch: {
selectedValue: {
handler(newValue, oldName) {
let value = newValue || {};
let _newLoca = value.location || {};
let _oldLoca = this.selfSelectedValue.location || {};
let mergeResult = {
location: {
lat: _newLoca.lat,
lng: _newLoca.lng,
},
address: value.address,
province: value.province,
city: value.city,
district: value.district,
};
//判断经纬度是否发生变化,如果变化,则需要重新画点
if (_oldLoca.lat !== _newLoca.lat || _oldLoca.lng !== _newLoca.lng) {
if (this.map && this.markerLayer) {
//1. 地图如果渲染完了,则把画点画上去
//2. 如果没有渲染完,也无需担心,在init会根据selfSelectedValue的最新值绘制
this._drawPoint(_newLoca.lat, _newLoca.lng, true);
}
}
this.selfSelectedValue = mergeResult;
},
immediate: true
}
},
directives: {
/**
* 封装指令,监听点击非目标元素之外的dom
* ***/
clickoutside: {
bind(el, binding, vnode) {
function documentHandler(e) {
console.log('documentHandler');
// 这里判断点击的元素是否是本身,是本身,则返回
if (el.contains(e.target)) {
console.log('el.contains(e.target)');
return false;
}
// 判断指令中是否绑定了函数
if (binding.expression) {
// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
binding.value(e);
}
}
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler;
document.addEventListener('click', documentHandler);
},
update() {
},
unbind(el, binding) {
// 解除事件监听
document.removeEventListener('click', el.__vueClickOutside__);
delete el.__vueClickOutside__;
}
}
},
methods: {
/**
* 初始化地图
* **/
initMap() {
//初始化地图
this.map = new TMap.Map('well-container', {
rotation: 20, //设置地图旋转角度
pitch: 0, //设置俯仰角度(0~45)
zoom: 16, //设置地图缩放级别
});
//初始化marker图层
this.markerLayer = new TMap.MultiMarker({
id: 'marker-layer',
map: this.map
});
//监听点击事件添加marker
this.map.on('click', this._clickMap);
//初始化点(在_drawPoint中,做了经纬度是否存在的判断)
let location = this.selfSelectedValue.location || {};
this._drawPoint(location.lat, location.lng, true);
},
/**
* 搜索框聚焦
* **/
handleFoucus(e) {
console.log('handleFoucus');
this.showAddressList = true;
},
/**
* 搜索框失焦
* **/
handleBlur() {
console.log('handleBlur');
this.showAddressList = false;
},
/**
* 搜索框内容发生变化
* timeout是为了防抖
* **/
handleSearch() {
this.showAddressList = true;
console.log('handleSearch');
clearTimeout(this.timeout);
if (!this.searchKey) {
this.addressList = [];
} else {
this.timeout = setTimeout(() => {
axios({
url: `/wellTencentMap/ws/place/v1/suggestion?keyword=${this.searchKey}&key=${this.mapKey}`,
method: 'GET'
}).then(res => {
this.addressList = (res.data && res.data.data) || [];
}).catch(err => {
console.log(err);
});
}, 300);
}
},
/**
* 选中搜索列表中的某一项,row格式如下:
* {
* "id":"1594670327289385140",
* "title":"人才好娃幼儿园",
* "address":"辽宁省铁岭市银州区三眼井巷1",
* "category":"教育学校:幼儿园",
* "type":0,
* "location":{
* "lat":42.292420809,
* "lng":123.857382405
* },
* "adcode":211202,
* "province":"辽宁省",
* "city":"铁岭市",
* "district":"银州区"
* }* **/
handleSelect(row) {
console.log(JSON.stringify(row));
this.searchKey = row.title;
//searchKey发生变化了,需触发搜索
this.handleSearch();
let value = {
location: row.location,
address: row.address,
province: row.province,
city: row.city,
district: row.district
};
this.selfSelectedValue = value;
this._notifyParent(value);
//selectedValue发生变化了,需重新绘制点
this._drawPoint(row.location.lat, row.location.lng, true);
//选中之后需触发失去焦点
this.handleBlur();
},
/**
* 根据经纬度在地图上标注
* @param lat 纬度
* @param lng 经度
* @param isUpdateCenter 是否更新地图中心点,有以下三种情况:
* 1. 外部传入的点信息发生变化时,需更新中心点
* 2. 选中搜索列表的某一项时,需更新中心点
* 3. 点击地图标记点时,不需要更新中心点
* **/
_drawPoint(lat, lng, isUpdateCenter) {
//先清空点
this.markerLayer.setGeometries([]);
if (!lat || !lng) {
return;
}
//更新地图中心位置
if (isUpdateCenter) {
this.map.setCenter(
new TMap.LatLng(lat, lng)
);
}
this.markerLayer.add({
position: new TMap.LatLng(lat, lng)
});
},
/**
* 通知父组件,标记的点发生了变化
* **/
_notifyParent(value) {
// this.$emit('update:value', selectedValue);
// this.$emit('update:selectedValue', selectedValue);
this.$emit('selected-change', value);
},
/**
* 点击地图
* 1. 根据经纬度画点
* 2, 根据经纬度逆向查询到地址详细信息
* 3. 通知父组件
* **/
_clickMap(evt){
console.log('点击地图:', evt);
this._drawPoint(evt.latLng.lat, evt.latLng.lng, false);
let locationParam = evt.latLng.lat + ',' + evt.latLng.lng;
axios({
url: '/wellTencentMap/ws/geocoder/v1/?location=' + locationParam + '&key=' + this.mapKey + '&get_poi=0',
method: 'GET'
}).then(res => {
console.log('【' + locationParam + '】逆地址解析结果:', res);
let result = (res.data && res.data.result);
if (!result) {
// this.$message.error(res.data.message);
alert(res.data.message);
return;
}
let ad_info = result.ad_info || {};
let value = {
location: result.location,
address: result.address,
province: ad_info.province,
city: ad_info.city,
district: ad_info.district
};
this.selfSelectedValue = value;
this._notifyParent(value);
}).catch(err => {
console.log('逆地址解析失败', err);
});
},
}
};
</script>
<style lang="less" scoped>
.well-map {
/*position: relative;*/
line-height: normal;
.search-row {
position: relative;
/*line-height: normal;*/
width: 100%;
margin: 12px 0 4px 0;
/*left: 20px;*/
/*top: 20px;*/
z-index: 99009;
.input-wrap {
height: 32px;
line-height: 32px;
display: flex;
> input {
box-sizing: border-box;
margin: 0;
position: relative;
width: 100%;
height: 100%;
padding: 4px 11px;
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
background-color: #fff;
/*background-image: none;*/
border: 1px solid #d9d9d9;
border-radius: 4px 0 0 4px;
transition: all 0.3s;
border-right: none;
&:hover {
border-color: #40a9ff;
border-right-width: 1px !important;
}
&:focus {
border-color: #40a9ff;
border-right-width: 1px !important;
outline: 0;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
}
> button {
padding: 0 15px;
border-radius: 0 4px 4px 0;
color: #fff;
background: #1890ff;
border-color: #1890ff;
box-shadow: none;
border: none;
width: 82px;
height: 100%;
cursor: pointer;
&:hover, &:focus {
color: #fff;
background: #40a9ff;
border-color: #40a9ff;
outline: none;
}
&:active {
color: #fff;
background: #096dd9;
border-color: #096dd9;
outline: none;
}
}
}
> ul {
position: absolute;
top: 100%;
left: 0;
width: 100%;
background: rgba(252, 250, 250, 0.918);
border: 1px solid #f1f1f1;
font-size: 13px;
color: #5a5a5a;
max-height: 280px;
overflow-y: auto;
list-style: none;
padding: 0;
margin: 0;
> li {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: 100%;
border-bottom: 1px solid #f1f1f1;
padding: 10px;
margin: 0;
cursor: pointer;
&:hover {
background: #eff6fd;
}
.title {
display: block;
line-height: normal;
margin-bottom: 4px;
}
.other-info {
font-size: 12px;
color: #b9b9b9;
display: block;
line-height: normal;
}
}
}
}
.well-map-container {
width: 100%;
height: 300px;
}
.selected-info {
background: #ecf5ff;
padding: 10px 14px;
color: #565656;
font-size: 13px;
> div {
margin-bottom: 4px;
.label {
color: #757575;
}
&:last-child {
margin-bottom: 0;
}
}
}
}
</style>
3. 使用
- 引入腾讯APIjs文件。在vue项目的index.html中引入,其中key需换成第一步申请到的key。
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=JDKBZ-****"></script>
- 设置代理。在vue.config.js文件中,添加配置。
devServer: {
proxy: {
"/wellTencentMap": {
target: "https://apis.map.qq.com",
changeOrigin: true,
ws: true,
pathRewrite: {
'^/wellTencentMap': '' //重写接口
}
},
}
}
- 替换mapKey,组件实现逻辑中的mapKey需换上面申请到的key。
data() {
return {
mapKey: 'JDKBZ-****',
};
},
- 使用组件。(此处我的组件名为well-tencent-map)
<well-tencent-map :selectedValue="selectedValue" @selected-change="mapSelectedChange"></well-tencent-map>
- 参数:
selectedValue:可不传、可传null、支持异步获取回来的数据。若传入,格式如下: { location: { lat: null, lng: null, }, address: null, province: null, city: null, district: null }
- 事件:
selected-change:当标记的点发生变化时,触发。