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 腾讯地图坐标
拾取坐标系统

posted @ 2025-05-25 15:54  ®Geovin Du Dream Park™  阅读(20)  评论(0)    收藏  举报