drew 5 лет назад
Родитель
Сommit
903053ac8c
2 измененных файлов с 295 добавлено и 12 удалено
  1. 281 0
      src/main/vue/src/components/AddressPicker.vue
  2. 14 12
      src/main/vue/src/main.js

+ 281 - 0
src/main/vue/src/components/AddressPicker.vue

@@ -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>

+ 14 - 12
src/main/vue/src/main.js

@@ -19,20 +19,22 @@ import 'element-ui/lib/theme-chalk/index.css';
 // import VueAMap from "vue-amap";
 // Vue.use(VueAMap);
 // VueAMap.initAMapApiLoader({
-//     key: "bf91055058a47a7dc387e40ab6256a5f",
+//     key: 'bf91055058a47a7dc387e40ab6256a5f',
 //     plugin: [
-//         "Autocomplete",
-//         "PlaceSearch",
-//         "Scale",
-//         "OverView",
-//         "ToolBar",
-//         "MapType",
-//         "PolyEditor",
-//         "AMap.CircleEditor",
-//         "AMap.Geolocation",
+//         'Autocomplete',
+//         'PlaceSearch',
+//         'Scale',
+//         'OverView',
+//         'ToolBar',
+//         'MapType',
+//         'PolyEditor',
+//         'AMap.CircleEditor',
+//         'AMap.Geolocation',
+//         'AMap.DistrictSearch',
+//         'AMap.Geocoder'
 //     ],
-//     uiVersion: "1.0.11",
-//     v: "1.4.4",
+//     uiVersion: '1.1',
+//     v: '1.4.15'
 // });
 
 Vue.config.productionTip = false;