基于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>
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 }
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 })();
几个知识点
1.子组件调用父组件 需要在父组件上写 v-on:子组件监听方法="父组件方法" 子组件内调用用 this.$emit("子组件监听方法", "回掉数据");
2.子组件种props 默认是单向数据绑定 ,如果想在子组件中修改父组件通过props传过来的数据时可以这样写
父组件内::map-show.sync="showMap"
子组件内:this.$emit('update:mapShow', false);

浙公网安备 33010602011771号