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(涂聚文)
浙公网安备 33010602011771号