vue3: baidumap using typescript
项目结构:
/* * @creater: geovindu * @since: 2025-05-25 11:26:27 * @LastAuthor: geovindu * @lastTime: 2025-05-25 15:20:10 * @文件相对于项目的路径: \jsstudy\vamp\src\router\index.ts * @message: geovindu * @IDE: vscode * @Development: node.js 20, vuejs3.0 * @package: npm install vue-router@4 * @ISO: windows10 * @database: mysql 8.0 sql server 2019 postgresSQL 16 * Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved. */ import { createRouter, createWebHistory} from 'vue-router'; import App from '../App.vue'; // 正确导入路由类型 import type { RouteRecordRaw } from 'vue-router'; import baidu from '../BmapApp.vue'; import amap from '../AmapApp.vue'; const routes: RouteRecordRaw[] = [ { path: '/', name: 'Home', component: App }, { path: '/bmap', name: 'bmap', component: baidu }, { path: '/amap', name: 'amap', component: amap } // 添加其他路由 ]; const router = createRouter({ history: createWebHistory(), routes }); export default router;
<!-- * @creater: geovindu * @since: 2025-05-25 11:30:42 * @LastAuthor: geovindu * @lastTime: 2025-05-25 15:02:36 * @文件相对于项目的路径: \jsstudy\vamp\src\App.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. --> <script setup lang="ts"> import { RouterLink, RouterView } from 'vue-router' </script> <template> <header> <div id="app" class="wrapper"> <nav> <RouterLink to="/amap">amap</RouterLink> <RouterLink to="/bmap">bmap</RouterLink> </nav> </div> </header> <RouterView /> </template> <style scoped> header { line-height: 1.5; max-height: 100vh; } .logo { display: block; margin: 0 auto 2rem; } nav { width: 100%; font-size: 12px; text-align: center; margin-top: 2rem; } nav a.router-link-exact-active { color: var(--color-text); } nav a.router-link-exact-active:hover { background-color: transparent; } nav a { display: inline-block; padding: 0 1rem; border-left: 1px solid var(--color-border); } nav a:first-of-type { border: 0; } @media (min-width: 1024px) { header { display: flex; place-items: center; padding-right: calc(var(--section-gap) / 2); } .logo { margin: 0 2rem 0 0; } header .wrapper { display: flex; place-items: flex-start; flex-wrap: wrap; } nav { text-align: left; margin-left: -1rem; font-size: 1rem; padding: 1rem 0; margin-top: 1rem; } } </style>
<!-- * @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>
用的高德的地图经纬度数据,存在误差。
https://api.map.baidu.com/lbsapi/getpoint/index.html 百度点坐标
https://lbs.amap.com/tools/picker 高德地图坐标
https://lbs.qq.com/tool/getpoint/get-point.html 腾讯地图坐标
拾取坐标系统
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)