You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
11 KiB

7 months ago
<template>
<div style="display: flex">
<a-form-item-rest>
<div class="rightBox">
<div class="inputArea">
<div style="margin-right: 10px">经度</div>
<div class="lng">
<ns-input
v-model:value="lng"
type="number"
class="input"
placeholder="请输入经度"
@change="inputChange('lng', $event)" /> </div
><div style="margin: 0 10px">纬度</div>
<div class="lat">
<ns-input
v-model:value="lat"
type="number"
class="input"
placeholder="请输入纬度"
@change="inputChange('lat', $event)" />
</div>
</div>
<div class="inputSearch" style="margin: 15px 0 15px 0">
<label style="margin-right: 10px">地址</label>
<ns-input v-model:value="address" class="inputAdress" placeholder="请输入地址" />
<ns-button type="primary" @click="onSearch">查询</ns-button>
</div>
<div class="mapArea">
<div id="map-container" style="width: 100%"></div>
</div>
<div id="resultDiv" class="result" v-if="resultList.length">
<div class="title">搜索结果:</div>
<ul class="resultList">
<li
v-for="(item, index) in resultList"
:key="item['hotPointID']"
@click="clickItem(item)">
<a-row>
<a-col style="width: 40px; display: flex; align-items: center">
<EnvironmentTwoTone
:twoToneColor="item['hotPointID'] === checkedItem ? 'red' : ''"
:style="{
fontSize: '22px',
}"
/></a-col>
<a-col :span="20">
<p>{{ item.name }}</p> <p>地址: {{ item.address }}</p
><p v-if="item.phone">电话: {{ item.phone }}</p></a-col
>
</a-row>
<a-divider />
</li>
</ul>
<!-- <ul>
<li v-for="(item, index) in resultList" :key="index">
<a @click="clickItem(item)">{{ index + 1 + '-' + item.name }}</a>
</li>
</ul> -->
<a-pagination
size="small"
:total="total"
@change="changeHandle"
:show-total="(total) => ` 共 ${total} 个搜索结果`" />
</div>
</div>
</a-form-item-rest>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Pagination } from 'ant-design-vue';
import pointTransfer from './transfer';
import { EnvironmentTwoTone } from '@ant-design/icons-vue';
export default defineComponent({
name: 'NsTMap',
components: {
'a-pagination': Pagination,
EnvironmentTwoTone,
},
props: {
// 中心点坐标
centerPoint: {
type: Array,
},
// 纬度
longitude: {
type: String,
default: '',
},
// 经度
latitude: {
type: String,
default: '',
},
defaultAddress: {
type: String,
default: '',
},
toPoint: {
type: String,
default: 'WGS84',
},
fromPoint: {
type: String,
default: 'GCJ02',
},
},
emits: ['change'],
data() {
return {
T: '',
zoom: 12,
lng: '',
lat: '',
address: '',
resultList: [],
total: 0,
page: 1,
checkedItem: '',
};
},
watch: {
longitude: {
handler(val) {
if (this.longitude && this.latitude) {
let point = pointTransfer(
[this.longitude, this.latitude],
this.fromPoint,
this.toPoint,
);
this.lng = point[0].toFixed(8);
this.lat = point[1].toFixed(8);
this.$nextTick(() => {
// this.address = this.getAddress(this.T.LngLat(this.lng, this.lat));
let marker = new this.T.Marker(new this.T.LngLat(this.lng, this.lat));
this.map.addOverLay(marker);
this.map.centerAndZoom(new this.T.LngLat(this.lng, this.lat), 16);
this.$emit('change', [this.latitude, this.longitude, this.address]);
});
}
},
immediate: true,
deep: true,
},
latitude: {
handler(val) {
if (this.longitude && this.latitude) {
let point = pointTransfer(
[this.longitude, this.latitude],
this.fromPoint,
this.toPoint,
);
this.lng = point[0].toFixed(8);
this.lat = point[1].toFixed(8);
this.$nextTick(() => {
// this.address = this.getAddress(this.T.LngLat(this.lng, this.lat));
let marker = new this.T.Marker(new this.T.LngLat(this.lng, this.lat));
this.map.addOverLay(marker);
this.map.centerAndZoom(new this.T.LngLat(this.lng, this.lat), 16);
this.$emit('change', [this.latitude, this.longitude, this.address]);
});
}
},
immediate: true,
deep: true,
},
address(val) {
if (val) {
this.address = val;
this.$emit('change', [this.lat, this.lng, this.address]);
}
},
defaultAddress: {
handler(val) {
if (this.longitude && this.latitude) {
this.address = val;
// let point = pointTransfer(
// [this.longitude, this.latitude],
// this.fromPoint,
// this.toPoint,
// );
// this.lng = point[0].toFixed(8);
// this.lat = point[1].toFixed(8);
// this.$nextTick(() => {
// this.address = this.getAddress(this.T.LngLat(this.lng, this.lat));
// let marker = new this.T.Marker(new this.T.LngLat(this.lng, this.lat));
// this.map.addOverLay(marker);
// this.map.centerAndZoom(new this.T.LngLat(this.lng, this.lat), 16);
// this.$emit('change', [this.latitude, this.longitude, this.address]);
// });
}
},
immediate: true,
// deep: true,
},
},
mounted() {
this.init();
this.map = new this.T.Map('map-container');
if (this.centerPoint) {
this.map.centerAndZoom(new this.T.LngLat(this.centerPoint.join()), this.zoom);
} else {
this.map.centerAndZoom(new this.T.LngLat(118.433065, 31.352625), this.zoom);
}
// let cp = new this.T.CoordinatePickup(this.map, { callback: this.getLngLat });
let geocode: any = new this.T.Geocoder();
this.map.addEventListener('click', (e) => {
geocode.getLocation(e.lnglat, (result: Recordable) => {
this.address = result.getAddress();
this.getLngLat(e.lnglat);
});
});
// cp.addEvent();
},
methods: {
init() {
// const script = document.createElement('script');
// script.type = 'text/javascript';
// script.src = 'http://api.tianditu.gov.cn/api?v=4.0&tk=b5311fc44ebe2d76a7738ae3b351fe28';
// document.body.appendChild(script);
if (typeof window.T !== 'undefined') {
console.log('初始化资源成功');
this.T = window.T;
} else {
console.log('初始化资源失败,查看项目index.html是否引用天地图');
}
},
async getLngLat(lnglat) {
let that = this;
// await this.getAddress(lnglat);
this.map.clearOverLays();
let marker = new this.T.Marker(new this.T.LngLat(lnglat.lng, lnglat.lat));
this.map.addOverLay(marker);
this.map.centerAndZoom(new this.T.LngLat(lnglat.lng, lnglat.lat), 16);
let point = pointTransfer([lnglat.lng, lnglat.lat], this.toPoint, this.fromPoint);
this.lng = point[0].toFixed(8);
this.lat = point[1].toFixed(8);
this.$emit('change', [point[1].toFixed(8), point[0].toFixed(8), this.address]);
},
async getAddress(lnglat) {
let that = this;
this.geocode = new this.T.Geocoder();
return await this.geocode.getLocation(lnglat, function (result) {
that.address = result.getAddress();
});
},
onSearch() {
console.log(this.address);
this.map.clearOverLays();
let config = {
// pageCapacity: 10,
onSearchComplete: this.loaclSearchResult,
};
this.localsearch = new this.T.LocalSearch(this.map, config);
this.localsearch.search(this.address);
},
loaclSearchResult(result) {
// let that = this;
this.resultList = result.getPois();
this.total = result.getCount();
if (this.resultList.length > 0) {
let first = this.resultList[0];
let lonlat = first.lonlat.split(',');
this.map.centerAndZoom(new this.T.LngLat(lonlat[0], lonlat[1]), 16);
for (let i = 0; i < this.resultList.length; i++) {
const item = this.resultList[i];
let lonlat = item.lonlat.split(',');
let marker = new this.T.Marker(new this.T.LngLat(lonlat[0], lonlat[1]));
marker['otherData'] = item;
marker.addEventListener('click', (e) => {
this.lng = e.lnglat.lng;
this.lat = e.lnglat.lat;
if (e.target['otherData']) {
this.checkedItem = e.target['otherData']['hotPointID'];
}
this.getAddress(e.lnglat);
this.map.centerAndZoom(new this.T.LngLat(e.lnglat.lng, e.lnglat.lat), 16);
let point = pointTransfer([this.lng, this.lat], this.toPoint, this.fromPoint);
this.$emit('change', [point[1].toFixed(8), point[0].toFixed(8), this.address]);
});
this.map.addOverLay(marker);
}
}
},
changeHandle(page) {
this.map.clearOverLays();
if (this.page < page) {
this.localsearch.nextPage();
} else {
this.localsearch.previousPage();
}
this.page = page;
},
clickItem(item) {
let lonlat = item.lonlat.split(',');
this.checkedItem = item['hotPointID'];
this.lng = lonlat[0];
this.lat = lonlat[1];
this.address = item.address + item.name;
this.map.centerAndZoom(new this.T.LngLat(lonlat[0], lonlat[1]), 16);
let point = pointTransfer([this.lng, this.lat], this.toPoint, this.fromPoint);
this.$emit('change', [point[1].toFixed(8), point[0].toFixed(8), this.address]);
},
},
});
</script>
<style lang="less" scoped>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
#map-container {
width: 100%;
height: 400px;
}
.leftBox,
.rightBox {
flex: 1;
}
.inputArea {
display: flex;
line-height: 30px;
}
.inputSearch {
.inputAdress {
width: 344px;
margin-right: 10px;
}
}
.resultList {
p {
margin-bottom: 0;
}
}
#resultDiv {
width: 100%;
ul {
list-style: none;
padding-left: 0;
li {
cursor: pointer;
}
}
}
:deep(.ant-divider) {
display: block !important;
margin: 4px 0;
}
</style>