由于赶项目,搜索获取某个位置信息实现后并未解决点击地图也可以获取相应的位置信息,后来实现,以此记录:
需求:可以搜索点位,也可以在地图上点击获取位置的详细信息,并制作成组件
过程:通过查询发现原来用的搜索组件并不支持给予初始值,自然也无法把点图上点击的地点位置信息获取后显示在搜索框中,提炼成组件以后也无法回显,只能用input输入,再增加搜索后的提示列表来模拟:
代码如下:
主页面vue文件
<template> <div class="contain"> <div v-if="primitiveData.locationName"> 搜索:{{primitiveData.name}},详细地址为:{{primitiveData.locationName}},经度:{{primitiveData.longitude}},纬度:{{primitiveData.latitude}} </div> <div> <el-input v-model="location" placeholder="定位" readonly @click.native="siteDialog=true"></el-input> </div> <Site :dialogShow.sync="siteDialog" @locationSure="locationSure" :primitiveData="primitiveData"></Site> </div> </template> <script> import Site from '@/components/site' export default { name: 'AMapDemo', components: { Site }, data() { return { location:'', siteDialog:false, primitiveData:{} } }, methods: { locationSure(val) { // 定位地址 console.log(val) this.location = val.name this.primitiveData =val }, } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style lang="scss" scoped> .amap-demo { width: 100%; height: 600px; position: relative; } .search-box { height: 35px; margin: 10px auto; width: calc(100% - 20px); // border-radius:16px; box-shadow: none; background: #ffff; border: 1px solid #e6e6e6; .search-box-wrapper { input { background: #fff; padding-left: 20px; } .search-btn { color: #2A67FE; width: 90px; height: 20px; box-sizing: border-box; border-left: 1px solid #D7D7D7; } } } </style>
组件vue页面:
<template> <div v-if="dialogShow"> <el-dialog title="定位" width="520px" :before-close="hide" :visible.sync="dialogShow" :close-on-click-modal="false" append-to-body class="site"> <el-row class="app-container home"> <el-col :span="24" class="box"> <el-amap ref="map" vid="amapDemo" :center="center" :zoom="zoom" class="amap-demo" :events="events"> <el-amap-marker :position="center" key="100"></el-amap-marker> </el-amap> <div class="searchBox"> <el-input v-model="inputValue" placeholder="搜索地名或者地址" id="tipinput" prefix-icon="el-icon-search" class="searchInput"></el-input> <div class="searchContainer"> <div class="searchItem" v-for="(item, index) in list" :key="item.id" :style="activeIndex === index && 'background: #ecf5ff'" @click="itemChange(item, index)"> <div>{{item.name}}</div> <div style="color:#999;font-size:12px;">{{item.address}}</div> </div> </div> </div> </el-col> </el-row> <div slot="footer" class="dialog-footer"> <el-button @click="hide">取 消</el-button> <el-button type="primary" @click="save">确 定</el-button> </div> </el-dialog> </div> </template> <script> export default { name: "site", components: {}, props: { dialogShow: {}, primitiveData: {} }, data() { return { tabIndex: '', list: [], activeIndex: '', zoom: 12, center: [118.02, 24.48], searchOption: { citylimit: false }, inputValue: '', searchResult: { address: '', latitude: '', longitude: '', name: '', type: '', country: '', province: '', city: '', area: '', township: '', street: '', neighborhood: '', locationName: '' }, events: { // 地图上的点击事件 click: (e) => { this.$nextTick(() => { let that = this that.position = [e.lnglat.lng, e.lnglat.lat] let geocoder = new AMap.Geocoder({}); geocoder.getAddress(that.position, function(status, result) { if (status === 'complete' && result.info === 'OK') { let obj = result.regeocode.addressComponent that.inputValue = obj.province + obj.city + obj.district + obj.township + obj.street + obj.streetNumber + (obj.building || '') } }); }) } } } }, computed: {}, watch: { dialogShow(val) { if (val) { this.inputValue = this.primitiveData.name this.list = [] } }, inputValue(value) { if (value) { // 监听输入内容 this.initMapByInput() } } }, mounted() {}, methods: { itemChange(n, index) { const that = this; that.activeIndex = index // 输入后搜索出来的,反地理编码出来的参数有所不同 let lng = n.lng || n.longitude || n.location.lng let lat = n.lat || n.latitude || n.location.lat let name = n.name || '' that.inputValue = name that.zoom = 13 that.position = [lng, lat] that.searchResult.address = n.address that.searchResult.latitude = lat that.searchResult.longitude = lng that.searchResult.name = name let geocoder = new AMap.Geocoder({}); geocoder.getAddress(that.position, function(status, result) { if (status === 'complete' && result.info === 'OK') { let obj = result.regeocode.addressComponent that.searchResult.locationName = obj.province + obj.city + obj.district + obj.township + obj.street + obj.streetNumber + (n.address || obj.building || '') } }); }, initMapByInput() { let that = this // 自动搜索插件 AMap.plugin('AMap.Autocomplete', () => { let autoOptions = { city: '全国' }; let autoComplete = new AMap.Autocomplete(autoOptions) autoComplete.search(that.inputValue, function(status, e) { if (status === 'complete' && e.info === 'OK') { if (e.tips && e.tips.length > 0) { let tips = e.tips.filter((i) => { return i.location && i.address.length > 0 }) let tip = tips[0] that.center = [tip.location.lng, tip.location.lat] that.zoom = 13 that.position = [tip.location.lng, tip.location.lat] that.list = tips that.searchResult.address = tip.address that.searchResult.latitude = tip.location.lat that.searchResult.longitude = tip.location.lng that.searchResult.name = tip.name let geocoder = new AMap.Geocoder({}); geocoder.getAddress(that.position, function(status, result) { if (status === 'complete' && result.info === 'OK') { let obj = result.regeocode.addressComponent that.searchResult.locationName = obj.province + obj.city + obj.district + obj.township + obj.street + tip.address } }); } else { that.list = [] that.searchResult = [] } } }); }); }, // 保存提交 save() { this.$emit('locationSure', this.searchResult) this.$emit('update:primitiveData', this.searchResult) this.hide() }, // 关闭弹框 hide() { this.dataShow = false this.inputValue = '' this.$emit("update:dialogShow", false) }, }, }; </script> <style lang="scss" scoped> ul, dl { padding: 0; margin: 0; list-style-type: none; } ::-webkit-scrollbar { display: none; } .amap-demo { width: 100%; height: 600px; position: relative; } .site /deep/ { .el-dialog__body { padding: 0; border-bottom: 1px solid #E4E4E4; } .app-container { padding: 0; } .search-box { height: 35px; margin: 10px auto; width: calc(100% - 20px); // border-radius:16px; box-shadow: none; background: #ffff; border: 1px solid #e6e6e6; .search-box-wrapper { input { background: #fff; padding-left: 20px; } .search-btn { color: #2A67FE; width: 90px; height: 20px; box-sizing: border-box; border-left: 1px solid #D7D7D7; } } } } .searchBox { width: 100%; height: 230px; border-radius: 10px 10px 0 0; background: #fff; font-size: 13px; color: #333333; position: absolute; bottom: 0; left: 0; z-index: 999; margin-top: 10px; overflow: hidden; .searchContainer { height: 180px; margin-top: 10px; overflow-y: auto; width: 100%; padding: 0 10px; box-sizing: border-box; } .searchItem { color: #333; font-size: 13px; text-align: left; padding: 7px 10px; display: flex; justify-content: space-between; border-bottom: 1px solid #e6e6e6; cursor: pointer; } } ::v-deep .el-vue-search-box-container .search-tips { width: 100%; top: 100%; max-height: 190px; overflow: auto; } .active { background: #DBE5F2; } .searchInput { margin: 0px 10px; background: #F7F8FA; border-radius: 16px; margin-top: 5px; height: 32px; width: calc(100% - 20px); box-sizing: border-box; } </style>
地图的引入可以参考上一篇,由于vue-amap是根据element的框架开发,为了方便也引入了element ui。详细代码下载:https://gitee.com/yuexiayunsheng/amapdemo