| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- <template>
- <div class="map-wrapper">
- <div class="search-controls">
- <div class="search-input-group">
- <div>
- <input
- v-model="searchQuery"
- @keyup.enter="executeSearch"
- placeholder="输入地点或地址"
- class="search-input"
- />
- <button @click="executeSearch" class="search-button" style="margin-left: 5px;">搜索</button>
- </div>
- <div style="margin-left: 10px;">
- <input v-model="longitude" class="search-input">
- <input v-model="latitude" class="search-input">
- <button @click="confirmAddress" class="search-button" style="margin-left: 5px;">确认</button>
- </div>
- </div>
-
- <div v-if="searchResults.length" class="search-results">
- <div
- v-for="(result, index) in searchResults"
- :key="index"
- class="result-item"
- @click="selectSearchResult(result)"
- >
- <h3>{{ result.title }}</h3>
- <p>{{ result.address }}</p>
- </div>
- </div>
- </div>
- <div ref="mapElement" class="bmap-container"></div>
- <div v-if="selectedPoint" class="coordinates-display">
- 经度: {{ selectedPoint.lng.toFixed(6) }},
- 纬度: {{ selectedPoint.lat.toFixed(6) }}
- <p v-if="selectedTitle">地名: {{ selectedTitle }}</p>
- <p v-if="selectedAddress">地址: {{ selectedAddress }}</p>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted, onBeforeUnmount } from 'vue'
- const mapElement = ref(null)
- const mapInstance = ref(null)
- const searchQuery = ref('')
- const searchResults = ref([])
- const selectedPoint = ref(null)
- const selectedAddress = ref('')
- const selectedTitle = ref('')
- const longitude = ref('')
- const latitude = ref('')
- let geocoder = null
- // 状态常量
- const BMAP_STATUS_SUCCESS = ref(0)
- const initializeMap = () => {
- const BMap = window.BMap
- BMAP_STATUS_SUCCESS.value = window.BMAP_STATUS_SUCCESS
-
- mapInstance.value = new BMap.Map(mapElement.value)
- const initialPoint = new BMap.Point(117.026817,31.968348)
- mapInstance.value.centerAndZoom(initialPoint, 12)
- mapInstance.value.enableScrollWheelZoom(true)
- geocoder = new BMap.Geocoder()
- mapInstance.value.addEventListener('click', handleMapClick)
- }
- const handleMapClick = async (e) => {
- // clearMarkers()
- // addMarker(e.point)
- selectedPoint.value = e.point
- await getAddressFromPoint(e.point)
- }
- // 修正后的搜索方法
- const executeSearch = () => {
- if (!searchQuery.value.trim()) return
- const BMap = window.BMap
- const localSearch = new BMap.LocalSearch(mapInstance.value, {
- onSearchComplete: (results) => {
- if (localSearch.getStatus() === BMAP_STATUS_SUCCESS.value) {
- // 新版POI获取方式
- const pois = [];
- const total = results.getCurrentNumPois();
- for (let i = 0; i < total; i++) {
- const poi = results.getPoi(i);
- if (poi) {
- pois.push({
- title: poi.title,
- address: poi.address || '无地址信息',
- point: poi.point
- });
- }
- }
- searchResults.value = pois;
- }
- },
- pageCapacity: 10
- })
-
- localSearch.search(searchQuery.value)
- }
- const emit = defineEmits(['getPos'])
- const confirmAddress = () => {
- emit('getPos', {lon:longitude.value,lat:latitude.value});
- searchQuery.value = ''
- searchResults.value = []
- selectedAddress.value = ''
- selectedTitle.value = ''
- selectedPoint.value = null
- longitude.value = ''
- latitude.value = ''
- clearMarkers()
- mapInstance.value.clearOverlays()
- }
- const selectSearchResult = (result) => {
- clearMarkers()
- mapInstance.value.panTo(result.point)
- addMarker(result.point)
- selectedPoint.value = result.point
- getAddressFromPoint(result.point)
-
- searchResults.value = []
- }
- const addMarker = (point) => {
- const marker = new BMap.Marker(point,{
- enableDragging: false, // 关闭标记拖拽
- })
- mapInstance.value.addOverlay(marker)
- convertPoint(point.lng, point.lat)
-
- // marker.addEventListener('click', () => {
- // showInfoWindow(marker, point)
- // })
-
- mapInstance.value.addEventListener('click', (e) => {
- if (e.overlay) return // 当点击覆盖物时不执行地图操作
- // 其他地图点击逻辑...
- })
- }
- const convertPoint = (lng, lat) => {
- const BMap = window.BMap
- if (mapInstance.value.getMapType() === BMAP_NORMAL_MAP) {
- return new BMap.Point(lng, lat)
- }
- // 处理百度坐标偏移
- const convertor = new BMap.Convertor()
- convertor.translate([new BMap.Point(lng, lat)], 1, 5, (res) => {
- if (res.status === 0) {
- return res.points[0]
- }
- })
- }
- const showInfoWindow = (marker, point) => {
- const infoWindow = new BMap.InfoWindow(`
- <div class="info-window">
- <h4>位置详情</h4>
- <p>经度: ${point.lng.toFixed(6)}</p>
- <p>纬度: ${point.lat.toFixed(6)}</p>
- ${selectedAddress.value ? `<p>地址: ${selectedAddress.value}</p>` : ''}
- </div>
- `)
- marker.openInfoWindow(infoWindow)
- }
- const clearMarkers = () => {
- mapInstance.value.clearOverlays()
- }
- const getAddressFromPoint = (point) => {
- return new Promise((resolve) => {
- geocoder.getLocation(point, (result) => {
- if (result) {
- selectedAddress.value = result.address
- selectedTitle.value = result?.content?.poi_region[0]?.name
- longitude.value = result?.point?.lng?.toFixed(6)
- latitude.value = result?.point?.lat?.toFixed(6)
- resolve(result.address)
- }
- })
- })
- }
- onMounted(() => {
- const script = document.createElement('script')
- script.src = `https://api.map.baidu.com/api?v=3.0&ak=tHCKI9rDMnTgxHPYsk95hGExEbYqkcIn&callback=initMap`
- document.head.appendChild(script)
- window.initMap = () => {
- initializeMap()
- }
- })
- onBeforeUnmount(() => {
- if (mapInstance.value) {
- mapInstance.value.removeEventListener('click', handleMapClick)
- mapInstance.value.destroy()
- }
- })
- </script>
- <style>
- .map-wrapper {
- position: relative;
- height: 500px;
- width: 100%;
- }
- .bmap-container {
- height: 100%;
- width: 100%;
- }
- .search-controls {
- position: absolute;
- top: 10px;
- left: 10px;
- z-index: 1000;
- background: rgba(255, 255, 255, 0.9);
- padding: 15px;
- border-radius: 8px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
- width: calc(100% - 20px);
- }
- .search-input-group {
- display: flex;
- gap: 8px;
- margin-bottom: 10px;
- }
- .search-input {
- flex: 1;
- padding: 8px;
- border: 1px solid #ddd;
- border-radius: 4px;
- }
- .search-button {
- padding: 8px 15px;
- background: #3385ff;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- }
- .search-results {
- max-height: 300px;
- overflow-y: auto;
- }
- .result-item {
- padding: 10px;
- border-bottom: 1px solid #eee;
- cursor: pointer;
- transition: background 0.2s;
- }
- .result-item:hover {
- background: #f5f5f5;
- }
- .coordinates-display {
- position: absolute;
- bottom: 20px;
- left: 20px;
- background: rgba(255, 255, 255, 0.9);
- padding: 15px;
- border-radius: 8px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
- }
- .info-window {
- padding: 10px;
- min-width: 200px;
- }
- </style>
|