vue+高德实现的小功能

通过本篇博客,你会学习到在vue项目的基础上,引入高德地图、自制点标记、轨迹绘制。欢迎大家访问我其他博客网站(微信公众号、掘金),都是同名(极客三刀流)

1. 准备工作

1. 搭建你自己的vue项目

2. 成为高德开发者

按照官方文档(准备-地图 JS API 2.0|高德地图API)创建API,记住你的key、安全秘钥,我绑定的服务为Web端

3. npm安装Loader

bash 复制代码
 npm i @amap/amap-jsapi-loader --save

创建地图

下面的标题1-3的实现步骤 都能在官方文档中找到(JS API 结合 Vue 使用-基础-进阶教程-地图 JS API 2.0|高德地图API)

1. 创建地图容器

html 复制代码
<template>  
  <div id = "container">  
  
  </div>  
</template>

2. 设置地图样式

css 复制代码
<style>  
#container {  
  margin: auto auto;  
  width: calc(100vw - 200px);  
  height: calc(100vh - 50px);  
}  
</style>

3. js部分代码

js 复制代码
<script setup>
import { onMounted, onUnmounted } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";

let map = null;

onMounted(() => {
  window._AMapSecurityConfig = {
    securityJsCode: "「你申请的安全密钥」",
  };
  AMapLoader.load({
    key: "[你申请的key]", // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
  })
    .then((AMap) => {
      map = new AMap.Map("container", {
        // 设置地图容器id
        viewMode: "3D", // 是否为3D地图模式
        zoom: 11, // 初始化地图级别
        center: [116.397428, 39.90923], // 初始化地图中心点位置
      });
    })
    .catch((e) => {
      console.log(e);
    });
});

onUnmounted(() => {
  map?.destroy();
});
</script>

4. 完整代码

下面以浙大为例

4.1. 效果

浙大地图

html 复制代码
<template>  
  <div id="container">  
  
  </div>  
</template>  
  
<script setup>  
import {onMounted, onUnmounted} from "vue";  
import AMapLoader from "@amap/amap-jsapi-loader";  
  
let map = null;  // 地图命名  
  
onMounted(() => {  
  window._AMapSecurityConfig = {  
    securityJsCode: "「你申请的安全密钥」",  
  };  
  
  AMapLoader.load({  
    key: "[你申请的key]", // 申请好的Web端开发者Key,首次调用 load 时必填  
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15    plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']  
  })  
      .then((AMap) => {  
        map = new AMap.Map("container", {  
          // 设置地图容器id  
          viewMode: "3D", // 是否为3D地图模式  
          rotateEnable: true, //是否开启地图旋转交互 鼠标右键 + 鼠标画圈移动 或 键盘Ctrl + 鼠标左键画圈移动  
          pitchEnable: true,  
          zoom: 19, // 初始化地图级别  
          center: [120.08344, 30.302504], // 初始化地图中心点位置  
        });  
  
  
  
        AMap.plugin(['AMap.ControlBar', 'AMap.ToolBar'], function () { //异步加载插件  
          var controlBar = new AMap.ControlBar({ //控制地图旋转插件  
            position: {  
              right: '10px',  
              top: '10px'  
            }  
          });  
          map.addControl(controlBar);  
          var toolBar = new AMap.ToolBar({ //地图缩放插件  
            position: {  
              right: '40px',  
              top: '110px'  
            }  
          });  
          map.addControl(toolBar)  
        });  
  
      })  
      .catch((e) => {  
        console.log(e);  
      });  
  
  
});  
  
onUnmounted(() => {  
  map?.destroy();  
});  
</script>  
  
<style>  
#container {  
  margin: auto auto;  
  width: calc(100vw - 200px);  
  height: calc(100vh - 50px);  
}  
  
/* 点标记 */.custom-content-marker {  
  text-align: center;  
  width: 190px;  
  height: 90px;  
  border-radius: 50%;  
  border: 2px solid #0004a1;  
  background: rgba(183, 226, 255, 0.7);  
}  
</style>

自制点标记

其他基础的点标记,可以在官方文档中默认点标记-点标记-进阶教程-地图 JS API 2.0|高德地图API找到

1. 效果

2. css代码

css 复制代码
/* 点标记 */
.custom-content-marker {  
  text-align: center;  
  width: 90px;  
  line-height: 40px;  
  height: 90px;  
  border-radius: 45px;  
  border: 2px solid #0004a1;  
  background: rgb(183, 226, 255);  
}

3. 点标记代码

js 复制代码
// 自定义点标记  
const content = `<div class="custom-content-marker">  
   <h3>内部自定义样式</h3>  
  </div>`  
const marker = new AMap.Marker({  
  position: new AMap.LngLat(120.084153, 30.302651), // 点标记位置  
  offset: new AMap.Pixel(0, 0), // 偏移量  
  title: 'zju',  
  content: content, // 自定义点标记内容  
});  
map.add(marker); // 加入地图

4. 完整代码

html 复制代码
<template>  
  <div id="container">  
  
  </div>  
</template>  
  
<script setup>  
import {onMounted, onUnmounted} from "vue";  
import AMapLoader from "@amap/amap-jsapi-loader";  
  
let map = null;  // 地图命名  
  
onMounted(() => {  
  window._AMapSecurityConfig = {  
    securityJsCode: "「你申请的安全密钥」",  
  };  
  
  AMapLoader.load({  
    key: "[你申请的key]", // 申请好的Web端开发者Key,首次调用 load 时必填  
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15    
    plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']  
  })  
      .then((AMap) => {  
        map = new AMap.Map("container", {  
          // 设置地图容器id  
          viewMode: "3D", // 是否为3D地图模式  
          rotateEnable: true, //是否开启地图旋转交互 鼠标右键 + 鼠标画圈移动 或 键盘Ctrl + 鼠标左键画圈移动  
          pitchEnable: true,  
          zoom: 19, // 初始化地图级别  
          center: [120.08344, 30.302504], // 初始化地图中心点位置  
        });  

        AMap.plugin(['AMap.ControlBar', 'AMap.ToolBar'], function () { //异步加载插件  
          var controlBar = new AMap.ControlBar({ //控制地图旋转插件  
            position: {  
              right: '10px',  
              top: '10px'  
            }  
          });  
          map.addControl(controlBar);  
          var toolBar = new AMap.ToolBar({ //地图缩放插件  
            position: {  
              right: '40px',  
              top: '110px'  
            }  
          });  
          map.addControl(toolBar)  
        });  
  
        // 自定义点标记  
        const content = `<div class="custom-content-marker">  
           <h3>内部自定义样式</h3>  
          </div>`  
        const marker = new AMap.Marker({  
          position: new AMap.LngLat(120.084153, 30.302651), // 点标记位置  
          offset: new AMap.Pixel(0, 0), // 偏移量  
          title: 'zju',  
          content: content, // 自定义点标记内容  
        });  
        map.add(marker); // 加入地图  
  
      })  
      .catch((e) => {  
        console.log(e);  
      });  
});  
  
onUnmounted(() => {  
  map?.destroy();  
});  
</script>  
  
<style>  
#container {  
  margin: auto auto;  
  width: calc(100vw - 200px);  
  height: calc(100vh - 50px);  
}  
  
/* 点标记 */.custom-content-marker {  
  text-align: center;  
  width: 90px;  
  line-height: 40px;  
  height: 90px;  
  border-radius: 45px;  
  border: 2px solid #0004a1;  
  background: rgb(183, 226, 255);  
}  
</style>

动态轨迹实现

首先选择一种出行方式(如骑车、步行、开车等),可以参考官方文档路线规划-服务插件和工具-进阶教程-地图 JS API 2.0|高德地图API

下面我以骑车为例

1. 效果图

2. 代码

2.1. 新增plugins

在 plugins 中加入AMap.Riding

js 复制代码
AMapLoader.load({  
  key: "[你申请的key]", // 申请好的Web端开发者Key,首次调用 load 时必填  
  version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15  
  plugins: ["AMap.Scale", "AMap.Riding"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']  
})

2.2. 规划路径

打开控制台,观察result里的内容,不同出行方式,结果会有区别 选择自行车出行的话,要注意的result.routes[0].rides(因为会跟我们接下轨迹绘制有关系)

js 复制代码
//骑行导航  
var riding = new AMap.Riding({  
  map: map,  
  panel: "panel"  
});  
//根据起终点坐标规划骑行路线  
riding.search([120.084268,30.302119], [120.08541,30.301091], function (status, result) {  
  if (status === 'complete') {  
    console.log('绘制骑行路线完成', result)  
    const route = result.routes[0];  
    // console.log('route', route)  
	 route.rides.forEach(ride => {  
      ride.path.forEach(point => {  
        path.push(point)  
      })  
    })  
    // console.log(path)  
    drawLine()  
  } else {  
    console.log('骑行路线数据查询失败')  
  }  
});

2.3. 轨迹绘制

我将其命名为 drawLine

2.3.1. 引入图片
js 复制代码
import cyclePng from "@/assets/cycle.png";
2.3.2. path数组

用于存储路径点

js 复制代码
let path = [];// 存储路径点
2.3.3. drawLine

内部要设置定时器,最后别忘记关掉

js 复制代码
let cycleMarker = null
let index = 0;
const drawLine = () => {
  let polyLine = new AMap.Polyline({
    map: map,
    path: [],
    strokeColor: "#fed151",
    strokeOpacity: 1,
    strokeWeight: 6,
    strokeStyle: "solid",
    strokeDasharray: [10, 5],
    lineJoin: "round",
    lineCap: "round",
    cursor: "pointer",
    zIndex: 50
  });

  let index = 0;
  const interval = setInterval(() => {
    /**
     * 自行车图标
     * @type {AMap.Icon}
     */
    const cycleIcon = new AMap.Icon({
      size: new AMap.Size(40, 40), //图标大小
      image: cyclePng,
      imageSize: new AMap.Size(40, 40),
    });

    if (index < path.length) {
      polyLine.setPath(path.slice(0, index + 1));

      // 移除之前的图标如果存在
      if (cycleMarker) {
        cycleMarker.setMap(null);
        cycleMarker = null;
      }

      if (index > 0) {
        const startPoint = path[index - 1];
        const endPoint = path[index];

        // 计算方向(箭头的角度)
        const dx = endPoint[0] - startPoint[0];
        const dy = endPoint[1] - startPoint[1];
        const angle = Math.atan2(dy, dx) * (180 / Math.PI);

        /**
         * 自行车 marker
         * @type {Property.Marker}
         */
        cycleMarker = new AMap.Marker({
          map: map,
          position: endPoint,
          icon: cycleIcon,
          offset: new AMap.Pixel(-12, -24),
          angle: angle
        });
      } else {
        // 若只有一个点
        cycleMarker = new AMap.Marker({
          map: map,
          position: path[index],
          icon: cycleIcon,
          offset: new AMap.Pixel(-12, -24),
          angle: 0
        });
      }
      index++;
    } else {
      clearInterval(interval);
    }
  }, 300); // 每100ms读取一个点
}

完整代码

html 复制代码
<template>
  <div id="container">

  </div>
</template>

<script setup>
import {onMounted, onUnmounted} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import cyclePng from "@/assets/cycle.png";

let map = null;  // 地图命名
let path = [];// 存储路径点

onMounted(() => {
  window._AMapSecurityConfig = {
    securityJsCode: "「你申请的安全密钥」",
  };

  AMapLoader.load({
	key: "[你申请的key]", // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ["AMap.Scale", "AMap.Riding"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
  })
      .then((AMap) => {
        map = new AMap.Map("container", {
          // 设置地图容器id
          viewMode: "3D", // 是否为3D地图模式
          rotateEnable: true, //是否开启地图旋转交互 鼠标右键 + 鼠标画圈移动 或 键盘Ctrl + 鼠标左键画圈移动
          pitchEnable: true,
          zoom: 19, // 初始化地图级别
          center: [120.08344, 30.302504], // 初始化地图中心点位置
        });



        AMap.plugin(['AMap.ControlBar', 'AMap.ToolBar'], function () { //异步加载插件
          var controlBar = new AMap.ControlBar({ //控制地图旋转插件
            position: {
              right: '10px',
              top: '10px'
            }
          });
          map.addControl(controlBar);
          var toolBar = new AMap.ToolBar({ //地图缩放插件
            position: {
              right: '40px',
              top: '110px'
            }
          });
          map.addControl(toolBar)
        });

        // 自定义点标记
        const content = `<div class="custom-content-marker">
           <h3>内部自定义样式</h3>
          </div>`
        const marker = new AMap.Marker({
          position: new AMap.LngLat(120.084153, 30.302651), // 点标记位置
          offset: new AMap.Pixel(0, 0), // 偏移量
          title: 'zju',
          content: content, // 自定义点标记内容
        });
        map.add(marker); // 加入地图

        //骑行导航
        var riding = new AMap.Riding({
          map: map,
          panel: "panel"
        });
        //根据起终点坐标规划骑行路线
        riding.search([120.084268,30.302119], [120.08541,30.301091], function (status, result) {
          if (status === 'complete') {
            console.log('绘制骑行路线完成', result)
            const route = result.routes[0];
            // console.log('route', route)
            // console.log('route.rides.path', route.rides[0].path)
            route.rides.forEach(ride => {
              ride.path.forEach(point => {
                path.push(point)
              })
            })
            // console.log(path)
            drawLine()
          } else {
            console.log('骑行路线数据查询失败')
          }
        });


      })
      .catch((e) => {
        console.log(e);
      });
});

onUnmounted(() => {
  map?.destroy();
});

let cycleMarker = null
let index = 0;
const drawLine = () => {
  let polyLine = new AMap.Polyline({
    map: map,
    path: [],
    strokeColor: "#fed151",
    strokeOpacity: 1,
    strokeWeight: 6,
    strokeStyle: "solid",
    strokeDasharray: [10, 5],
    lineJoin: "round",
    lineCap: "round",
    cursor: "pointer",
    zIndex: 50
  });

  let index = 0;
  const interval = setInterval(() => {
    /**
     * 自行车图标
     * @type {AMap.Icon}
     */
    const cycleIcon = new AMap.Icon({
      size: new AMap.Size(40, 40), //图标大小
      image: cyclePng,
      imageSize: new AMap.Size(40, 40),
    });

    if (index < path.length) {
      polyLine.setPath(path.slice(0, index + 1));

      // 移除之前的图标如果存在
      if (cycleMarker) {
        cycleMarker.setMap(null);
        cycleMarker = null;
      }

      if (index > 0) {
        const startPoint = path[index - 1];
        const endPoint = path[index];

        // 计算方向(箭头的角度)
        const dx = endPoint[0] - startPoint[0];
        const dy = endPoint[1] - startPoint[1];
        const angle = Math.atan2(dy, dx) * (180 / Math.PI);

        /**
         * 自行车 marker
         * @type {Property.Marker}
         */
        cycleMarker = new AMap.Marker({
          map: map,
          position: endPoint,
          icon: cycleIcon,
          offset: new AMap.Pixel(-12, -24),
          angle: angle
        });
      } else {
        // 若只有一个点
        cycleMarker = new AMap.Marker({
          map: map,
          position: path[index],
          icon: cycleIcon,
          offset: new AMap.Pixel(-12, -24),
          angle: 0
        });
      }
      index++;
    } else {
      clearInterval(interval);
    }
  }, 300); // 每100ms读取一个点
}

</script>

<style>
#container {
  margin: auto auto;
  width: calc(100vw - 200px);
  height: calc(100vh - 50px);
}

/* 点标记 */
.custom-content-marker {
  text-align: center;
  width: 90px;
  line-height: 40px;
  height: 90px;
  border-radius: 45px;
  border: 2px solid #0004a1;
  background: rgb(183, 226, 255);
}
</style>
相关推荐
小小小小宇2 小时前
手写 zustand
前端
Hamm2 小时前
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
前端·vue.js·typescript
小小小小宇3 小时前
前端国际化看这一篇就够了
前端
大G哥3 小时前
PHP标签+注释+html混写+变量
android·开发语言·前端·html·php
whoarethenext3 小时前
html初识
前端·html
小小小小宇3 小时前
一个功能相对完善的前端 Emoji
前端
m0_627827523 小时前
vue中 vue.config.js反向代理
前端
Java&Develop3 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器
白泽talk4 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务
摆烂工程师4 小时前
全网最详细的5分钟快速申请一个国际 “edu教育邮箱” 的保姆级教程!
前端·后端·程序员