Vue结合百度地图(vue-baidu-map)实现多边形绘制与编辑全攻略

Vue结合百度地图(vue-baidu-map)实现多边形绘制与编辑全攻略

一、技术选型与组件安装

在Vue项目中集成百度地图功能,推荐使用官方维护的vue-baidu-map组件库。该库封装了百度地图JavaScript API,提供符合Vue响应式特性的组件接口。

1.1 安装配置步骤

  1. npm install vue-baidu-map --save

在项目入口文件(main.js)中全局注册组件:

  1. import Vue from 'vue'
  2. import BaiduMap from 'vue-baidu-map'
  3. Vue.use(BaiduMap, {
  4. // 必须填写有效的百度地图AK
  5. ak: '您的百度地图开发者密钥'
  6. })

1.2 基础地图组件

在组件模板中引入地图容器:

  1. <baidu-map
  2. class="map-container"
  3. :center="center"
  4. :zoom="zoom"
  5. @ready="mapReady">
  6. </baidu-map>

对应脚本配置:

  1. data() {
  2. return {
  3. center: {lng: 116.404, lat: 39.915},
  4. zoom: 15
  5. }
  6. },
  7. methods: {
  8. mapReady({BMap, map}) {
  9. this.BMap = BMap
  10. this.map = map
  11. }
  12. }

二、多边形绘制实现

2.1 基础绘制功能

使用bm-polygon组件创建静态多边形:

  1. <bm-polygon
  2. :points="polygonPoints"
  3. stroke-color="#ff0000"
  4. fill-color="#ff000020"
  5. :stroke-opacity="0.8"
  6. :fill-opacity="0.4">
  7. </bm-polygon>

数据结构示例:

  1. data() {
  2. return {
  3. polygonPoints: [
  4. {lng: 116.38, lat: 39.92},
  5. {lng: 116.42, lat: 39.92},
  6. {lng: 116.42, lat: 39.90},
  7. {lng: 116.38, lat: 39.90}
  8. ]
  9. }
  10. }

2.2 动态绘制实现

创建绘制管理器实现交互式绘制:

  1. methods: {
  2. startDrawing() {
  3. const drawingManager = new this.BMap.DrawingManager(this.map, {
  4. isOpen: true,
  5. enableDrawingTool: true,
  6. drawingToolOptions: {
  7. anchor: BMAP_ANCHOR_TOP_RIGHT,
  8. drawingModes: [BMAP_DRAWING_POLYGON]
  9. },
  10. polygonOptions: {
  11. strokeColor: '#ff0000',
  12. fillColor: '#ff000020'
  13. }
  14. })
  15. drawingManager.addEventListener('polygoncomplete', (polygon) => {
  16. const points = polygon.getPath()
  17. this.polygonPoints = points.map(point => ({
  18. lng: point.lng,
  19. lat: point.lat
  20. }))
  21. this.map.removeOverlay(polygon) // 移除默认绘制的图形
  22. this.drawCustomPolygon()
  23. })
  24. },
  25. drawCustomPolygon() {
  26. // 使用bm-polygon重新渲染
  27. }
  28. }

三、多边形编辑功能实现

3.1 基础编辑实现

百度地图API提供BMap.Polygon的编辑功能:

  1. methods: {
  2. enableEditing() {
  3. if (!this.currentPolygon) return
  4. const polygon = new this.BMap.Polygon(
  5. this.polygonPoints.map(p => new this.BMap.Point(p.lng, p.lat))
  6. )
  7. this.map.addOverlay(polygon)
  8. const editor = new this.BMap.PolygonEditor(this.map, polygon)
  9. editor.open()
  10. editor.addEventListener('adjust', (e) => {
  11. const paths = e.polygon.getPath()
  12. this.polygonPoints = paths.map(point => ({
  13. lng: point.lng,
  14. lat: point.lat
  15. }))
  16. })
  17. }
  18. }

3.2 自定义编辑控件

创建更友好的编辑界面:

  1. <div class="edit-controls">
  2. <button @click="addVertex">添加顶点</button>
  3. <button @click="removeVertex">删除顶点</button>
  4. <button @click="savePolygon">保存</button>
  5. </div>

实现顶点操作逻辑:

  1. methods: {
  2. addVertex(index) {
  3. if (index === undefined) {
  4. // 在中心点添加
  5. const bounds = this.getPolygonBounds()
  6. const center = bounds.getCenter()
  7. this.polygonPoints.splice(Math.floor(this.polygonPoints.length/2), 0, {
  8. lng: center.lng,
  9. lat: center.lat
  10. })
  11. } else {
  12. // 在指定位置插入
  13. const prev = this.polygonPoints[index]
  14. const next = this.polygonPoints[index+1] || this.polygonPoints[0]
  15. const midPoint = this.calculateMidPoint(prev, next)
  16. this.polygonPoints.splice(index+1, 0, midPoint)
  17. }
  18. },
  19. calculateMidPoint(p1, p2) {
  20. return {
  21. lng: (p1.lng + p2.lng) / 2,
  22. lat: (p1.lat + p2.lat) / 2
  23. }
  24. }
  25. }

四、高级功能实现

4.1 绘制状态管理

使用Vuex管理绘制状态:

  1. // store/modules/map.js
  2. const state = {
  3. isDrawing: false,
  4. currentPolygon: null
  5. }
  6. const mutations = {
  7. SET_DRAWING_STATE(state, isDrawing) {
  8. state.isDrawing = isDrawing
  9. },
  10. SET_CURRENT_POLYGON(state, polygon) {
  11. state.currentPolygon = polygon
  12. }
  13. }

4.2 持久化存储

实现多边形数据持久化:

  1. methods: {
  2. async savePolygon() {
  3. try {
  4. const response = await api.savePolygon({
  5. points: this.polygonPoints,
  6. name: '自定义区域'
  7. })
  8. this.$message.success('保存成功')
  9. } catch (error) {
  10. console.error('保存失败:', error)
  11. }
  12. },
  13. loadPolygons() {
  14. api.getPolygons().then(data => {
  15. this.savedPolygons = data
  16. })
  17. }
  18. }

4.3 性能优化策略

  1. 防抖处理:对频繁的坐标更新操作进行防抖
    ```javascript
    import { debounce } from ‘lodash’

methods: {
updatePolygon: debounce(function(points) {
// 实际更新逻辑
}, 300)
}

  1. 2. **复杂度控制**:当顶点数超过50时提示简化
  2. ```javascript
  3. computed: {
  4. isComplex() {
  5. return this.polygonPoints.length > 50
  6. }
  7. }

五、完整示例代码

  1. <template>
  2. <div class="map-wrapper">
  3. <baidu-map
  4. class="map"
  5. :center="center"
  6. :zoom="zoom"
  7. @ready="initMap">
  8. <bm-polygon
  9. v-if="polygonPoints.length > 2"
  10. :points="polygonPoints"
  11. stroke-color="#3388ff"
  12. fill-color="#3388ff30"
  13. @click="selectPolygon">
  14. </bm-polygon>
  15. <bm-drawing-manager
  16. v-if="isDrawing"
  17. @polygoncomplete="handlePolygonComplete"
  18. drawing-modes="['polygon']">
  19. </bm-drawing-manager>
  20. </baidu-map>
  21. <div class="controls">
  22. <button @click="startDrawing">开始绘制</button>
  23. <button @click="enableEditing" :disabled="!currentPolygon">编辑</button>
  24. <button @click="clearAll">清空</button>
  25. </div>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. data() {
  31. return {
  32. center: {lng: 116.404, lat: 39.915},
  33. zoom: 15,
  34. polygonPoints: [],
  35. isDrawing: false,
  36. currentPolygon: null,
  37. map: null,
  38. BMap: null
  39. }
  40. },
  41. methods: {
  42. initMap({BMap, map}) {
  43. this.BMap = BMap
  44. this.map = map
  45. },
  46. startDrawing() {
  47. this.isDrawing = true
  48. this.polygonPoints = []
  49. },
  50. handlePolygonComplete(e) {
  51. const points = e.getPath()
  52. this.polygonPoints = points.map(p => ({
  53. lng: p.lng,
  54. lat: p.lat
  55. }))
  56. this.isDrawing = false
  57. },
  58. enableEditing() {
  59. if (!this.polygonPoints.length) return
  60. const points = this.polygonPoints.map(p =>
  61. new this.BMap.Point(p.lng, p.lat)
  62. )
  63. const polygon = new this.BMap.Polygon(points)
  64. this.map.addOverlay(polygon)
  65. const editor = new this.BMap.PolygonEditor(this.map, polygon)
  66. editor.open()
  67. editor.addEventListener('adjust', (e) => {
  68. const paths = e.polygon.getPath()
  69. this.polygonPoints = paths.map(p => ({
  70. lng: p.lng,
  71. lat: p.lat
  72. }))
  73. })
  74. },
  75. clearAll() {
  76. this.polygonPoints = []
  77. this.isDrawing = false
  78. },
  79. selectPolygon() {
  80. // 选择逻辑
  81. }
  82. }
  83. }
  84. </script>
  85. <style>
  86. .map-wrapper {
  87. position: relative;
  88. width: 100%;
  89. height: 600px;
  90. }
  91. .map {
  92. width: 100%;
  93. height: 100%;
  94. }
  95. .controls {
  96. position: absolute;
  97. top: 20px;
  98. left: 20px;
  99. z-index: 999;
  100. }
  101. </style>

六、常见问题解决方案

  1. 地图不显示:检查AK是否正确,是否开启JS API权限
  2. 绘制功能失效:确认drawingManager是否正确初始化
  3. 编辑延迟:减少顶点数量或优化事件处理
  4. 跨域问题:配置百度地图服务端白名单

七、最佳实践建议

  1. 顶点数量控制在3-100个之间,过多顶点会影响性能
  2. 为多边形添加唯一标识符便于管理
  3. 实现撤销/重做功能提升用户体验
  4. 对大面积多边形进行简化处理
  5. 添加坐标系转换工具处理不同来源的数据

通过以上实现方案,开发者可以在Vue项目中高效地集成百度地图的多边形绘制与编辑功能,满足地理信息采集、区域管理等业务场景需求。实际开发中可根据具体需求调整界面交互和功能细节。