vue3: baidumap using typescript
项目结构:
<!--* @creater: geovindu* @since: 2025-05-25 11:32:26* @LastAuthor: geovindu* @lastTime: 2025-05-25 15:42:02* @文件相对于项目的路径: \jsstudy\vamp\src\components\BaiduMapMarker.vue* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
-->
<template><div class="map-container" ref="mapContainer" style="height: 600px;"></div>
</template><script lang="ts" setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';interface Hotel {name: string;content: string;center: string;type: number;icon: string;
}const props = defineProps<{hotels: Hotel[];ak: string;
}>();const mapContainer = ref<HTMLElement | null>(null);
let map: BMap.Map | null = null;
let infoWindow: BMap.InfoWindow | null = null;// 加载百度地图API
const loadBMapScript = (ak: string) => {return new Promise<void>((resolve, reject) => {if (window.BMap) {resolve();return;}const script = document.createElement('script');script.src = `https://api.map.baidu.com/api?v=3.0&ak=${ak}&callback=initBMap`;script.async = true;script.onload = () => resolve();script.onerror = (err) => reject(new Error(`加载百度地图API失败: ${err}`));document.head.appendChild(script);// 定义全局回调函数(window as any).initBMap = () => resolve();});
};// 初始化地图
const initMap = async () => {if (!mapContainer.value || !props.ak) {console.error('地图容器或API密钥未设置');return;}try {console.log('开始加载百度地图API...');await loadBMapScript(props.ak);console.log('百度地图API加载成功');// 创建地图实例map = new BMap.Map(mapContainer.value);// 设置中心点(深圳大致位置)const centerPoint = new BMap.Point(114.057868, 22.543099);map.centerAndZoom(centerPoint, 12);// 添加地图控件map.addControl(new BMap.NavigationControl());map.addControl(new BMap.ScaleControl());map.addControl(new BMap.OverviewMapControl());// 初始检查酒店数据updateMarkers();console.log('地图初始化完成');} catch (error: any) {console.error('加载百度地图失败:', error.message);}
};// 更新地图标记
const updateMarkers = () => {if (!map) return;// 清除现有标记map.clearOverlays();console.log('更新酒店标记:', props.hotels);if (!props.hotels || props.hotels.length === 0) {console.log('酒店数据为空');return;}const points: BMap.Point[] = [];props.hotels.forEach(hotel => {const [lng, lat] = hotel.center.split(',').map(Number);console.log('添加酒店标记:', hotel.name, '坐标:', lng, lat);const point = new BMap.Point(lng, lat);points.push(point);// 使用百度地图默认图标const icon = new BMap.Icon('https://api.map.baidu.com/images/marker_red_sprite.png',new BMap.Size(23, 25));// 创建标记const marker = new BMap.Marker(point, { icon });map.addOverlay(marker);// 添加标签const label = new BMap.Label(hotel.name, {offset: new BMap.Size(20, -10)});marker.setLabel(label);// 添加点击事件marker.addEventListener('click', () => {showInfoWindow(point, hotel);});});// 调整地图视野以显示所有标记if (points.length > 0) {map.setViewport(points);}
};// 显示信息窗口
const showInfoWindow = (point: BMap.Point, hotel: Hotel) => {if (!map) return;// 创建信息窗口if (!infoWindow) {infoWindow = new BMap.InfoWindow('', {width: 250,height: 100});}// 设置信息窗口内容infoWindow.setContent(`<div style="font-size: 14px;"><h4>${hotel.name}</h4><p>${hotel.content}</p></div>`);// 打开信息窗口map.openInfoWindow(infoWindow, point);
};onMounted(() => {initMap();
});// 监听酒店数据变化,更新标记
watch(() => props.hotels, () => {console.log('酒店数据发生变化,更新标记');if (map) {updateMarkers();}
});onUnmounted(() => {// 清理地图资源if (map) {map.clearOverlays();map = null;}infoWindow = null;
});
</script><style scoped>
.map-container {width: 100%;height: 100%;
}
</style>
<!--* @creater: geovindu* @since: 2025-05-25 11:32:26* @LastAuthor: geovindu* @lastTime: 2025-05-25 15:50:23* @文件相对于项目的路径: \jsstudy\vamp\src\BmapApp.vue* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package:* @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16* Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.
-->
<template><div id="app"><h1>深圳酒店百度地图</h1><div v-if="loading" class="loading-message">加载中...</div><div v-else-if="error" class="error-message">加载失败: {{ error.message }}</div><BaiduMapMarker v-else :hotels="hotels" :ak="baiduMapAK" /></div></template><script lang="ts" setup>import { ref, onMounted } from 'vue';import BaiduMapMarker from './components/BaiduMapMarker.vue';// 百度地图API密钥(确保替换为有效密钥)const baiduMapAK = ref('你的KEY');const hotels = ref<any[]>([]);const loading = ref(true);const error = ref<Error | null>(null);// 从JSON文件加载酒店数据const loadHotelData = async () => {try {const response = await fetch('hotels.json'); // 确保路径正确if (!response.ok) {throw new Error(`HTTP错误! 状态码: ${response.status}`);}const data = await response.json();hotels.value = data;console.log('酒店数据加载成功:', data);} catch (err: any) {console.error('加载酒店数据失败:', err);error.value = err;} finally {loading.value = false;}};onMounted(() => {loadHotelData();});</script><style>#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding: 0 20px;}h1 {color: #333;}.loading-message, .error-message {padding: 20px;margin: 20px;background-color: #f5f5f5;border-radius: 8px;}.error-message {color: #f56c6c;}</style>
输出:( 用高德的地图经纬度数据,存在误差。)