|
|
@@ -0,0 +1,281 @@
|
|
|
+<template>
|
|
|
+ <div class="map-wrapper">
|
|
|
+ <el-amap
|
|
|
+ ref="map"
|
|
|
+ :center="mapCenter"
|
|
|
+ :zoom="zoom"
|
|
|
+ class="map-view"
|
|
|
+ :events="mapEvents"
|
|
|
+ :expandZoomRange="true"
|
|
|
+ mapStyle="fresh"
|
|
|
+ >
|
|
|
+ <el-amap-marker
|
|
|
+ v-if="myPosition"
|
|
|
+ :position="myPosition"
|
|
|
+ content="<div class='my-position'><div>"
|
|
|
+ cursor="default"
|
|
|
+ vid="myposition"
|
|
|
+ >
|
|
|
+ </el-amap-marker>
|
|
|
+ <el-amap-marker
|
|
|
+ v-if="marker"
|
|
|
+ :position="marker"
|
|
|
+ :draggable="true"
|
|
|
+ :events="markerEvents"
|
|
|
+ cursor="default"
|
|
|
+ vid="choosepoint"
|
|
|
+ >
|
|
|
+ </el-amap-marker>
|
|
|
+ </el-amap>
|
|
|
+ <el-amap-search-box class="search-box" :search-option="searchOption" :on-search-result="onSearchResult">
|
|
|
+ </el-amap-search-box>
|
|
|
+ <div class="btn-locate" @click="locate">
|
|
|
+ <i
|
|
|
+ :class="{
|
|
|
+ 'el-icon-loading': locating,
|
|
|
+ 'el-icon-aim': !locating
|
|
|
+ }"
|
|
|
+ ></i>
|
|
|
+ </div>
|
|
|
+ <div class="btn-minus" @click="setZoom(-1)">
|
|
|
+ <i class="el-icon-minus"></i>
|
|
|
+ </div>
|
|
|
+ <div class="btn-plus" @click="setZoom(1)">
|
|
|
+ <i class="el-icon-plus"></i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ props: {
|
|
|
+ searchOption: {
|
|
|
+ type: Object,
|
|
|
+ default() {
|
|
|
+ return {
|
|
|
+ city: '全国',
|
|
|
+ citylimit: false
|
|
|
+ };
|
|
|
+ }
|
|
|
+ },
|
|
|
+ center: {
|
|
|
+ type: Array
|
|
|
+ },
|
|
|
+ zoom: {
|
|
|
+ type: Number,
|
|
|
+ default: 15
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ type: Array
|
|
|
+ },
|
|
|
+ lat: {},
|
|
|
+ lng: {},
|
|
|
+ address: {}
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ let self = this;
|
|
|
+ return {
|
|
|
+ locating: false,
|
|
|
+ myPosition: null,
|
|
|
+ marker: null,
|
|
|
+ mapEvents: {
|
|
|
+ complete: () => {
|
|
|
+ this.$refs.map.$$getInstance().setDefaultCursor('default');
|
|
|
+ },
|
|
|
+ click: e => {
|
|
|
+ this.marker = [e.lnglat.lng, e.lnglat.lat];
|
|
|
+ this.mapCenter = [e.lnglat.lng, e.lnglat.lat];
|
|
|
+ this.getGeolocation();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ markerEvents: {
|
|
|
+ dragend: e => {
|
|
|
+ this.marker = [e.lnglat.lng, e.lnglat.lat];
|
|
|
+ this.mapCenter = [e.lnglat.lng, e.lnglat.lat];
|
|
|
+ this.getGeolocation();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mapCenter: [121.480342, 31.236339]
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ if (this.center) {
|
|
|
+ this.mapCenter = this.center;
|
|
|
+ }
|
|
|
+ if (this.lat && this.lng) {
|
|
|
+ this.mapCenter = [this.lng, this.lat];
|
|
|
+ this.marker = [this.lng, this.lat];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ locate() {
|
|
|
+ this.locating = true;
|
|
|
+ let geolocation = new AMap.Geolocation({
|
|
|
+ enableHighAccuracy: true,
|
|
|
+ timeout: 10000
|
|
|
+ });
|
|
|
+ geolocation.getCurrentPosition();
|
|
|
+ AMap.event.addListener(geolocation, 'complete', data => {
|
|
|
+ this.locating = false;
|
|
|
+ this.mapCenter = [data.position.lng, data.position.lat];
|
|
|
+ this.myPosition = [data.position.lng, data.position.lat];
|
|
|
+ });
|
|
|
+ AMap.event.addListener(geolocation, 'error', err => {
|
|
|
+ this.locating = false;
|
|
|
+ console.log(err);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ onSearchResult(pois) {
|
|
|
+ let latSum = 0;
|
|
|
+ let lngSum = 0;
|
|
|
+ if (pois.length > 0) {
|
|
|
+ pois.forEach(poi => {
|
|
|
+ let { lng, lat } = poi;
|
|
|
+ lngSum += lng;
|
|
|
+ latSum += lat;
|
|
|
+ });
|
|
|
+ let center = {
|
|
|
+ lng: lngSum / pois.length,
|
|
|
+ lat: latSum / pois.length
|
|
|
+ };
|
|
|
+ this.mapCenter = [center.lng, center.lat];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ setZoom(d) {
|
|
|
+ this.$refs.map.$$getInstance().setZoom(this.$refs.map.$$getInstance().getZoom() + d);
|
|
|
+ },
|
|
|
+ getGeolocation() {
|
|
|
+ let lnglat = this.marker;
|
|
|
+ AMap.plugin('AMap.Geocoder', () => {
|
|
|
+ let geocoder = new AMap.Geocoder();
|
|
|
+ geocoder.getAddress(lnglat, (status, result) => {
|
|
|
+ if (status === 'complete' && result.info === 'OK') {
|
|
|
+ this.$emit('update:address', result.regeocode.formattedAddress);
|
|
|
+ this.$emit('update:lat', lnglat[1]);
|
|
|
+ this.$emit('update:lng', lnglat[0]);
|
|
|
+ this.$emit('pick', {
|
|
|
+ lnglat: {
|
|
|
+ lng: lnglat[0],
|
|
|
+ lat: lnglat[1]
|
|
|
+ },
|
|
|
+ ...result.regeocode
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ searchOption(option) {
|
|
|
+ if (option && option.city) {
|
|
|
+ var geocoder = new AMap.Geocoder({});
|
|
|
+
|
|
|
+ geocoder.getLocation(option.city, function(status, result) {
|
|
|
+ if (status === 'complete' && result.info === 'OK') {
|
|
|
+ console.log(result);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ lat() {
|
|
|
+ if (this.lat && this.lng) {
|
|
|
+ this.mapCenter = [this.lng, this.lat];
|
|
|
+ this.marker = [this.lng, this.lat];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ lng() {
|
|
|
+ if (this.lat && this.lng) {
|
|
|
+ this.mapCenter = [this.lng, this.lat];
|
|
|
+ this.marker = [this.lng, this.lat];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.map-wrapper {
|
|
|
+ position: relative;
|
|
|
+ border-radius: 4px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ overflow: hidden;
|
|
|
+ .map-view {
|
|
|
+ width: 100%;
|
|
|
+ height: 400px;
|
|
|
+ }
|
|
|
+ .btn-locate {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #666;
|
|
|
+ position: absolute;
|
|
|
+ left: 10px;
|
|
|
+ bottom: 10px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3);
|
|
|
+ &:active {
|
|
|
+ background: #f2f3f4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .btn-minus {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ font-size: 16px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ color: #666;
|
|
|
+ position: absolute;
|
|
|
+ left: 10px;
|
|
|
+ bottom: 50px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3);
|
|
|
+ &:active {
|
|
|
+ background: #f2f3f4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .btn-plus {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #666;
|
|
|
+ position: absolute;
|
|
|
+ left: 10px;
|
|
|
+ bottom: 90px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3);
|
|
|
+ &:active {
|
|
|
+ background: #f2f3f4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .search-box {
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ left: 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="less">
|
|
|
+.anchorBL,
|
|
|
+.amap-logo,
|
|
|
+.amap-copyright {
|
|
|
+ display: none !important;
|
|
|
+}
|
|
|
+
|
|
|
+.my-position {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 3px solid #fff;
|
|
|
+ background: #20a0ff;
|
|
|
+ box-shadow: 0 2px 2px rgba(0, 0, 0, 0.15);
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+</style>
|