基于AMap Vue组件地图选点实例

先看效果

 

上代码:

 1 <link href="~/static/css/approveagree.css" rel="stylesheet" />
 2 
 3 <link href="~/static/css/map.css" rel="stylesheet" />
 4 <script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.15&key=a6a719205689d2bed7cdcdece029869f&plugin=AMap.Autocomplete,AMap.PlaceSearch,AMap.Driving"></script>
 5 <!--引入UI组件库(1.0版本) -->
 6 <script src="http://webapi.amap.com/ui/1.0/main.js"></script>
 7 
 8 <div id="app" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow-y:hidden;">
 9     <div>当前地点</div>
10 
11     <table style="width:100%; border-collapse:collapse;">
12         <tr>
13             <td style="width:20%;border:1px solid #666;">center</td>
14             <td style="border:1px solid #666;">{{position.center}}</td>
15         </tr>
16         <tr>
17             <td style="width:20%;border:1px solid #666;">location</td>
18             <td style="border:1px solid #666;">{{position.location}}</td>
19         </tr>
20         <tr>
21             <td style="width:20%;border:1px solid #666;">position</td>
22             <td style="border:1px solid #666;">{{position.position}}</td>
23         </tr>
24         <tr>
25             <td style="width:20%;border:1px solid #666;">address</td>
26             <td style="border:1px solid #666;">{{position.address}}</td>
27         </tr>
28         <tr>
29             <td style="width:20%;border:1px solid #666;">type</td>
30             <td style="border:1px solid #666;">{{position.type}}//0查看 1选择地图</td>
31         </tr>
32     </table>
33     <button style="margin:0;" class="btn-page" type="primary" v-on:click="chooseMap">选地图</button>
34     <br />
35     <button style="margin:0;" class="btn-page" type="primary" v-on:click="viewMap">查看地图</button>
36     <map-selector :map-show.sync="showMap" :pos-data="position" v-on:mapselected="confirmPosition"></map-selector>
37 </div>
38 
39 <script src="~/Scripts/vue.components.js"></script>
40 <script type="text/javascript">
41     var app = new Vue({
42         el: '#app',
43         data: {
44             showMap: false,
45             position: {
46                 city: "北京市",
47                 center: [116.344115, 39.956228],
48                 location: [116.35525, 39.951394],
49                 position: "交大执行大厦",
50                 address: "交大执行大厦address",
51                 type: 1 //0查看 1选择地图
52             },
53         },
54         created: function () {
55         },
56         methods: {
57             chooseMap: function () {
58                 this.position.type = 1;
59                 this.showMap = true;
60             },
61             viewMap: function () {
62                 this.position.type = 0;
63                 this.showMap = true;
64             },
65             confirmPosition: function (data) {
66                 this.position = data;
67                 this.showMap = false;
68             }
69         }
70     });
71 </script>
HTML代码

 

  1 .ipt {
  2     margin: 0 0.2rem;
  3     display: block;
  4     width: 100%;
  5     padding: 0.12rem;
  6     padding-left: 0.6rem;
  7     border-radius: 0.06rem;
  8     border: 0.01rem solid #ccc;
  9     outline: none;
 10     font-size: 0.3rem;
 11 }
 12 
 13 .map-container {
 14     height: 100%;
 15     display: flex;
 16     flex-direction: column;
 17     position: relative;
 18     overflow: hidden;
 19     position: absolute;
 20     left:0;
 21     right:0;
 22     bottom:0;
 23     top: 100%;
 24     background-color:#fff;
 25     opacity: 0;
 26 }
 27 
 28     .map-container > .top {
 29         flex: 0 0 1rem;
 30         align-items: center;
 31         justify-content: center;
 32         display: flex;
 33     }
 34 
 35         .map-container > .top > input {
 36             margin: 0 0.2rem;
 37             display: block;
 38             width: 100%;
 39             padding: 0.12rem;
 40             border-radius: 0.06rem;
 41             border: 0.01rem solid #ccc;
 42             outline: none;
 43             font-size: 0.3rem;
 44             padding: 0.15rem;
 45             padding-left: 0.6rem;
 46             background: url("../img/searchbar_icon_search.png") no-repeat 0.1rem center;
 47             background-size: auto 60%;
 48         }
 49 
 50     .map-container > .map {
 51         flex: 1;
 52     }
 53 
 54 .map-show {
 55     transition: all .3s linear;
 56     top:0;
 57     opacity:1;
 58 }
 59 .map-hide {
 60     transition: all .3s linear;
 61     top:100%;
 62     opacity: 0;
 63 }
 64 #naviCon {
 65     position: fixed;
 66     left: 0.2rem;
 67     bottom: 0.2rem;
 68     right: 0.2rem;
 69     background-color: #fff;
 70     padding: 0.2rem;
 71     padding-bottom: 0;
 72     border-radius: 0.2rem;
 73     z-index: 200;
 74 }
 75 
 76     #naviCon > .info > div {
 77         font-size: 0.34rem;
 78         font-weight: bold;
 79     }
 80 
 81     #naviCon > .info > p {
 82         margin: 0.1rem 0;
 83         color: #555555;
 84         font-size: 0.3rem;
 85     }
 86 
 87     #naviCon > .navi {
 88         display: flex;
 89         align-items: center;
 90         border-top: 0.01rem solid #ccc;
 91     }
 92 
 93         #naviCon > .navi > div {
 94             flex: 1;
 95             display: flex;
 96             align-items: center;
 97             justify-content: center;
 98             line-height: 1rem;
 99         }
100 
101 #history {
102     display: flex;
103     flex-direction: column;
104     position: absolute;
105     top: 100%;
106     left: 0;
107     width: 100%;
108     height: 100%;
109     z-index: 400;
110     background-color: #fff;
111 }
112 
113     #history > .top {
114         flex: 0 0 1rem;
115         align-items: center;
116         justify-content: center;
117         display: flex;
118         border-bottom: 0.02rem solid #ccc;
119     }
120 
121         #history > .top > div:first-child {
122             flex: 1 1 auto;
123             display: flex;
124         }
125 
126             #history > .top > div:first-child > input {
127                 margin: 0 0.2rem;
128                 display: block;
129                 width: 100%;
130                 padding: 0.12rem;
131                 border-radius: 0.06rem;
132                 border: 0.01rem solid #ccc;
133                 outline: none;
134                 font-size: 0.3rem;
135                 padding: 0.15rem;
136                 padding-left: 0.6rem;
137                 background: url("../img/searchbar_icon_search.png") no-repeat 0.1rem center;
138                 background-size: auto 60%;
139             }
140 
141         #history > .top > div:last-child {
142             flex: 0 0 0.5rem;
143             margin-right: 0.2rem;
144             height: 0.4rem;
145             background: url("../img/search_icon_close.png") no-repeat right center;
146             background-size: 50% auto;
147         }
148 
149         #history > .top > .option {
150             color: #333;
151             flex: 0 0 1.3rem;
152             display: flex;
153             text-align: center;
154             padding: 0 0.1rem;
155             line-height: 0.56rem;
156         }
157 
158             #history > .top > .option > div {
159                 width: 1.3rem;
160                 overflow: hidden;
161                 text-overflow: ellipsis;
162                 white-space: nowrap;
163                 background: url("../img/searchbar_icon_down.png") no-repeat right center;
164                 background-size: 0.2rem auto;
165                 padding-right: 0.14rem;
166             }
167 
168     #history > .list {
169         flex: 1;
170         padding: 0.2rem;
171         padding-top: 0;
172         box-sizing: border-box;
173         position: relative;
174     }
175 
176         #history > .list > .items {
177             overflow-y: auto;
178             position: absolute;
179             left: 0rem;
180             top: 0;
181             bottom: 0rem;
182             right: 0rem;
183             font-size: 0.3rem;
184             padding: 0 0.2rem 0.2rem 0.2rem;
185         }
186 
187             #history > .list > .items > .item {
188                 border-bottom: 0.01rem solid #eee;
189                 display: flex;
190                 align-items: center;
191                 padding: 0.2rem;
192             }
193 
194                 #history > .list > .items > .item > .left {
195                     flex: 0 0 0.6rem;
196                     height: 0.6rem;
197                 }
198 
199                 #history > .list > .items > .item > .type0 {
200                     background: url("../img/search_list_type0.png") no-repeat center center;
201                     background-size: 0.2rem auto;
202                 }
203 
204                 #history > .list > .items > .item > .type1 {
205                     background: url("../img/search_list_type1.png") no-repeat center center;
206                     background-size: 0.2rem auto;
207                 }
208 
209                 #history > .list > .items > .item .pos {
210                     font-size: 0.3rem;
211                 }
212 
213                 #history > .list > .items > .item .address {
214                     font-size: 0.24rem;
215                     color: #666;
216                 }
217 
218                 #history > .list > .items > .item .more {
219                     width: 100%;
220                     text-align: center;
221                     color: #555;
222                     line-height: 0.8rem;
223                 }
224 
225 #map {
226     width: 100%;
227     height: 100%;
228 }
229 
230 #btnOK {
231     position: fixed;
232     bottom: 0.2rem;
233     left: 0.2rem;
234     right: 0.2rem;
235     line-height: 0.8rem;
236     background-color: #3296FA;
237     border-radius: 0.04rem;
238     z-index: 300;
239     text-align: center;
240     color: #fff;
241 }
242 
243 .poi-con {
244     background-color: #fff;
245     padding: 0.2rem;
246     border-radius: 0.08rem;
247 }
248 
249     .poi-con > div:first-child {
250         font-size: 0.3rem;
251     }
252 
253     .poi-con > div:last-child {
254         margin-top: 0.1rem;
255         font-size: 0.24rem;
256         color: #666;
257     }
258 
259 .showhis {
260     animation: showHistory ease 0.2s;
261     animation-fill-mode: forwards;
262 }
263 
264 .hidehis {
265     animation: hideHistory ease 0.1s;
266     animation-fill-mode: forwards;
267 }
268 
269 @keyframes showHistory {
270     from {
271         top: 100%;
272     }
273 
274     to {
275         top: 0;
276     }
277 }
278 
279 @keyframes hideHistory {
280     from {
281         top: 0;
282     }
283 
284     to {
285         top: 100%;
286     }
287 }
288 
289 .amap-ui-mobi-city-picker {
290     font-size: medium;
291 }
292 
293     .amap-ui-mobi-city-picker .search-box {
294         font-size: medium;
295     }
296 
297     .amap-ui-mobi-city-picker .city_fixed_title,
298     .amap-ui-mobi-city-picker .listgroup .title {
299         font-size: medium;
300     }
301 
302     .amap-ui-mobi-city-picker.light .top_group .citylist .item {
303         font-size: medium;
304     }
CSS代码
  1 (function () {
  2     Vue.component("map-selector", {
  3         data: function () {
  4             return {
  5                 city: '北京市',
  6                 searchTxt: '',
  7                 center: [],
  8                 map: null,
  9                 marker: null,
 10                 userMarker: null,
 11                 infoWindow: null,
 12                 selectPoi: {},
 13                 showHistory: false,
 14                 historyList: [],
 15                 dataName: 'history_list',
 16                 showMore: false,
 17                 posInfo: null,
 18                 searchObj: {
 19                     pageIndex: 1,
 20                     pageSize: 10
 21                 },
 22                 goNavi: '未导航',
 23                 cityPicker: null,
 24                 paramsData: null,
 25             }
 26         },
 27         template: `<div :class="{'map-container':true,'map-show':mapShow,'map-hide':!mapShow}">
 28                         <div class="top" v-show="posData.type==1">
 29                             <input type="text" placeholder="搜索地点..." readonly v-on:click="homeSearch" />
 30                         </div>
 31                         <div class="map" id="map"></div>
 32                         <div id="history" v-bind:class="{showhis: showHistory }" v-show="showHistory">
 33                                 <div class="top">
 34                                     <div>
 35                                         <input ref="realSearch" v-on:input="searchPlace" v-model="searchTxt" type="text" placeholder="搜索地点..."/>
 36                                     </div>
 37                                     <div class="option">
 38                                         <div v-if="searchTxt.length==0" v-on:click="changeCity">{{city}}</div>
 39                                         <div v-else v-on:click="goSearch">搜索</div>
 40                                     </div>
 41                                     <div v-on:click="showHistory=false"></div>
 42                                 </div>
 43                                 <div class="list">
 44                                     <div class="items">
 45                                         <div class="item" v-for="item in historyList" v-on:click="selectPosition(item)">
 46                                             <div class="left" v-bind:class="{type0:item.stype==0,type1:item.stype==1}"></div>
 47                                             <div>
 48                                                 <div class="pos">{{item.name}}</div>
 49                                                 <div class="address">{{item.address}}</div>
 50                                             </div>
 51                                         </div>
 52                                         <div class="item" v-if="showMore" v-on:click="loadMore">
 53                                             <div class="more">加载更多..</div>
 54                                         </div>
 55                                     </div>
 56                                 </div>
 57                            </div>                        
 58                         <div id="btnOK" v-on:click="confirmPoi">
 59                             确定
 60                         </div>
 61                     </div>`,
 62 
 63         mounted: function () {
 64             this.initData();
 65             this.initCityUI();
 66         },
 67         props: ['posData', 'mapShow'],
 68         methods: {
 69             initData() {
 70 
 71                 var that = this;
 72                 //{"city":"北京市","center":[116.344115,39.956228],"location":[116.35525,39.951394],"position":"交大执行大厦","address":"交大执行大厦address","index":0,"type":1}
 73                 if (that.posData) {
 74                     //if (that.posData.type == 0) {//0 查看 1 选点
 75                     //    that.searchMode = false;
 76                     //    document.title = "查看位置点";
 77                     //} else {
 78                     //    that.searchMode = true;
 79                     //    document.title = "选择位置点";
 80                     //}
 81                     that.city = that.posData.city;
 82                 }
 83 
 84                 that.initMap();
 85             },
 86             initCityUI: function () {
 87                 var that = this;
 88                 AMapUI.loadUI(['misc/MobiCityPicker'], function (MobiCityPicker) {
 89                     that.cityPicker = new MobiCityPicker({
 90                         //topGroups: ..., // 顶部城市列表
 91                     });
 92                     //监听城市选中事件
 93                     that.cityPicker.on('citySelected', function (cityInfo) {
 94 
 95                         that.city = cityInfo.name;
 96                         //选中的城市信息
 97                         console.log(cityInfo);
 98                         //隐藏城市列表
 99                         that.cityPicker.hide();
100                     });
101 
102                 });
103             },
104             initMap: function () {
105                 var that = this;
106                 that.map = new AMap.Map('map', {
107                     resizeEnable: true, //是否监控地图容器尺寸变化
108                     zoom: 11, //初始化地图层级
109                     // center: [116.397428, 39.90923] //初始化地图中心点
110                 });
111 
112                 that.map.on('complete', function () {
113                     console.log('地图加载完毕,标注点;');
114                     if (that.posData.position) {
115                         that.selectPoi.name = that.posData.position;
116 
117                     }
118                     if (that.posData.address) {
119                         that.selectPoi.address = that.posData.address;
120                     }
121 
122                     if (that.posData.location[0] > 0 && that.posData.location[1] > 0) {
123                         that.addViewMarker(that.posData.location);
124                         that.selectPoi.location = {};
125                         that.selectPoi.location.lat = that.posData.location[0];
126                         that.selectPoi.location.lng = that.posData.location[1];
127                     };
128                     if (that.posData.center[0] > 0 && that.posData.center[1] > 0) {
129                         that.userMarker.setPosition(that.posData.center);
130                         that.userMarker.show();
131                         that.selectPoi.center = that.posData.center;
132                     }
133                 });
134 
135                 // 创建一个 icon
136                 var userIcon = new AMap.Icon({
137                     size: new AMap.Size(60, 60),
138                     image: 'imgs/usevar_map_icon_my.png',
139                     imageSize: new AMap.Size(60, 60),
140                     imageOffset: new AMap.Pixel(0, 0)
141                 });
142 
143                 that.userMarker = new AMap.Marker({
144                     position: [0, 0],
145                     icon: userIcon,
146                     offset: new AMap.Pixel(-13, -30),
147                     map: that.map,
148                     visible: false
149                 });
150 
151             },
152             homeSearch: function () {
153                 var that = this;
154                 this.showHistory = true;
155                 this.showMore = false;
156                 this.searchTxt = '';
157 
158                 setTimeout(function () {
159                     that.$refs.realSearch.focus();
160                 }, 500);
161                 this.loadHistoryList();
162             },
163             searchPlace: function (e) {
164                 this.searchTxt = e.target.value;
165                 this.searchObj.pageIndex = 1;
166                 if (this.searchTxt.length > 0) {
167                     this.showMore = true;
168                     this.searchResult();
169                 }
170                 else {
171                     this.showMore = false;
172                     this.loadHistoryList();
173                 }
174             },
175             goSearch: function () {
176                 var sName = this.searchTxt;
177                 var sObj = { stype: 0, name: sName };
178                 var listData = this.getHistoryList();
179                 var hasPos = false;
180                 listData.forEach(function (obj) {
181                     if (obj.name === sName && obj.stype === 0) {
182                         hasPos = true;
183                     }
184                 });
185                 if (!hasPos) {
186                     listData.unshift(sObj);
187                     this.historyList = listData;
188                     this.saveHistoryList();
189                 }
190                 this.showMore = true;
191                 this.searchObj.pageIndex = 1;
192                 this.searchResult();
193 
194             },
195             searchResult: function () {
196 
197 
198                 //构造地点查询类
199                 var that = this;
200                 var placeSearch = new AMap.PlaceSearch({
201                     // type: "加油站", // 兴趣点类别
202                     pageSize: that.searchObj.pageSize, // 单页显示结果条数
203                     pageIndex: that.searchObj.pageIndex, // 页码
204                     city: that.city, // 兴趣点城市
205                     citylimit: true,  //是否强制限制在设置的城市内搜索
206                     //map: that.map, // 展现结果的地图实例
207                     autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
208                 });
209                 placeSearch.search(this.searchTxt, function (status, result) {
210 
211                     if (that.searchObj.pageIndex == 1) {
212                         that.historyList = [];
213                     }
214 
215                     if (result.poiList) {
216                         var pois = result.poiList.pois;
217                         if (pois.length > 0) {
218                             pois.forEach(function (poi) {
219                                 poi.stype = 1;
220                             })
221                             that.historyList = that.historyList.concat(pois);
222                             if (that.historyList.length >= result.poiList.count) {
223                                 that.showMore = false;
224                             }
225                         }
226                     } else {
227                         that.showMore = false;
228                     }
229                 });
230             },
231             loadMore: function () {
232                 this.searchObj.pageIndex += 1;
233                 this.searchResult();
234             },
235             selectPosition: function (item) {
236 
237                 if (item.stype == 0) {
238                     //分页查询
239                     this.showMore = true;
240                     this.searchTxt = item.name;
241                     this.searchObj.pageIndex = 1
242                     this.searchResult();
243                 } else {
244                     this.showHistory = false;
245 
246                     var listData = this.getHistoryList();
247 
248                     var hasObj = false;
249                     listData.forEach(function (obj) {
250                         if (obj.name === item.name && obj.stype === 1) {
251                             hasObj = true;
252                         }
253                     });
254                     if (!hasObj) {
255                         item.stype = 1;
256                         listData.unshift(item);
257                     }
258                     this.historyList = listData;
259                     this.saveHistoryList();
260                     this.selectPoi = item;
261                     this.addSelectMarker([item.location.lng, item.location.lat]);
262                 }
263             },
264             //确定
265             confirmPoi() {
266                 if (this.posData.type == 0) {
267                     this.$emit('update:mapShow', false);
268                 } else {
269                     var that = this;
270                     var selPoi = this.selectPoi;
271                     var postObj = {
272                         position: selPoi.name,
273                         address: selPoi.address,
274                         lat: selPoi.location.lat,
275                         lng: selPoi.location.lng,
276                         location: [selPoi.location.lat, selPoi.location.lng],
277                     };
278 
279                     this.$emit("mapselected", postObj);
280                 }
281               
282             },
283             //选择地点后标点
284             addViewMarker(position) {
285                 var that = this;
286                 if (that.marker == null) {
287                     marker = new AMap.Marker({
288                         position: position,
289                         offset: new AMap.Pixel(-13, -30),
290                         map: that.map,
291                     });
292                     that.marker = marker;
293                 }
294                 that.marker.setPosition(position);
295 
296                 that.map.setCenter(position);
297                 that.map.setFitView();
298                 that.markerClick();
299             },
300             //选择地点后标点
301             addSelectMarker(position) {
302                 var that = this;
303                 if (that.marker == null) {
304                     marker = new AMap.Marker({
305                         position: position,
306                         offset: new AMap.Pixel(-13, -30),
307                         map: that.map,
308                     });
309 
310                     marker.on('click', that.markerClick);
311                     that.marker = marker;
312                 }
313                 that.marker.setPosition(position);
314 
315                 that.map.setCenter(position);
316                 that.userMarker.hide();
317                 that.map.setFitView();
318                 that.userMarker.show();
319                 that.markerClick();
320             },
321             markerClick: function () {
322                 var that = this;
323                 var content = "<div class='poi-con'><div>" + that.selectPoi.name + "</div><div>" + that.selectPoi.address + "</div></div>"
324                 that.infoWindow = new AMap.InfoWindow({
325                     isCustom: true,  //使用自定义窗体
326                     content: content,
327                     offset: new AMap.Pixel(-5, -30)
328                 });
329 
330                 that.infoWindow.open(that.map, that.marker.getPosition());
331             },
332             //加载历史数据
333             loadHistoryList: function () {
334                 var listData = this.getHistoryList();
335                 this.historyList = listData;
336             },
337             saveHistoryList: function () {
338                 this.setCookie(this.dataName, JSON.stringify(this.historyList));
339             },
340             getHistoryList: function () {
341                 var _data = this.getCookie(this.dataName);
342                 if (_data != '') {
343                     return JSON.parse(this.getCookie(this.dataName));
344                 } else {
345                     return [];
346                 }
347             },
348 
349             //切换城市
350             changeCity: function () {
351                 this.cityPicker.show();
352             },
353             setCookie: function (c_name, value) {
354                 document.cookie = c_name + "=" + escape(value)
355             },
356             getCookie: function (c_name) {
357                 if (document.cookie.length > 0) {
358                     var c_start = document.cookie.indexOf(c_name + "=")
359 
360                     if (c_start != -1) {
361                         var value = document.cookie.split('=')[1];
362                         var cIndex = value.indexOf(';');
363                         if (cIndex != -1) {
364                             value = value.substr(0, cIndex);
365                         }
366                         return unescape(value);
367                     }
368                 }
369                 return ""
370             }
371         }
372     });
373 
374 })();
JS代码(Vue组件)

 

几个知识点

1.子组件调用父组件 需要在父组件上写  v-on:子组件监听方法="父组件方法"  子组件内调用用   this.$emit("子组件监听方法", "回掉数据");

2.子组件种props 默认是单向数据绑定 ,如果想在子组件中修改父组件通过props传过来的数据时可以这样写

  父组件内::map-show.sync="showMap" 

  子组件内:this.$emit('update:mapShow', false); 

posted @ 2019-10-18 16:03  崔国亮  阅读(681)  评论(0)    收藏  举报