vue3引入腾讯地图api 绘制多边形及地图插点功能(非ts)

1,513 阅读5分钟

这是我第一次写文,文笔不好,凑合看看,有不对的请指正
最近做一个需求,需要在vue3项目中使用腾讯地图的api,也是头一次使用腾讯地图,把我的经验分享一下

地图引入

在系统根目录下的index.html文件中引入 (看有些文档说在public目录下的index.html文件 我的项目中index.html是在根目录下的)

<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=申请的key值&libraries=visualization"></script>

页面中html内容

<template>
    <div id="container" />
</template>

页面中js内容

function initMap() {
  // 定义地图中心点坐标
  const center = new window.TMap.LatLng(纬度,经度)
  // 定义map变量,调用 TMap.Map() 构造函数创建地图

  const map = new window.TMap.Map(document.getElementById('container'), {
    center, // 设置地图中心点坐标
    zoom: 8.5, // 设置地图缩放级别
    mapStyleId: 'style1', // 设置地图样式
  })
}
onMounted(() => {
  initMap()
})

页面中样式

<style scoped>
#container {
  /*地图(容器)显示大小*/
  width: 100%;
  height: 100%;
}
</style>

好的 目前到这一步 最基础的地图 就引入ok了
下面说说这一次做的功能

案例1 插点画圆

第一版呢 是像图中一样 选中一个位置为圆心,插点并圈出周围一公里地界,而后返回标点的经纬度

image.png 实现代码

// 初始中心点
const mapCenter = [40.46, 131.45]
function initMap() {
  // 定义地图中心点坐标
  const center = new window.TMap.LatLng(...mapCenter)
  // 定义map变量,调用 TMap.Map() 构造函数创建地图

  const map = new window.TMap.Map(document.getElementById('container'), {
    center, // 设置地图中心点坐标
    zoom: 8.5, // 设置地图缩放级别
    mapStyleId: 'style1', // 设置地图样式
  })
  //创建圆形
  const circle = new window.TMap.MultiCircle({
    map,
    styles: {
      // 设置圆形样式
      circle: new window.TMap.CircleStyle({
        color: 'rgba(41,91,255,0.16)',
        showBorder: true,
        borderColor: 'rgba(41,91,255,1)',
        borderWidth: 2,
      }),
    },
    //circle配置项
    //初始时无选中地点 所以radius为0
    geometries: [
      {
        styleId: 'circle',
        center,
        radius: 0,//圆的半径 单位为米
      },
    ],
  })
  let marker
  //(回显时触发 在传入的坐标创建点和圆)
  if (defaultCenter) {
    const defaultPoint = new TMap.LatLng(...defaultCenter)
    marker = new TMap.MultiMarker({
      id: 'marker-layer',
      map,
      styles: {
      //点的尺寸↓
        marker: new TMap.MarkerStyle({
          width: 20,
          height: 35,
        }),
      },
      geometries: [
        {
          id: 'mapMarker',
          styleId: 'marker',
          position: defaultPoint,
          properties: {
            title: 'marker',
          },
        },
      ],
    })
    //设置圆中心点并修改圆半径为1km
    circle.setGeometries([
      {
        styleId: 'circle',
        center: defaultPoint,
        radius: 1000,
      },
    ])
  }
  //监听地图点击事件
  map.on('click', (evt) => {
    // lat 纬度 lng 经度
    const lat = evt.latLng.getLat().toFixed(6)
    const lng = evt.latLng.getLng().toFixed(6)
    const clickPoint = new window.TMap.LatLng(lat, lng)
    //设置圆中心点并修改圆半径
    circle.setGeometries([
      {
        styleId: 'circle',
        center: clickPoint,
        radius: 1000,
      },
    ])
    //如果还未创建插点 则创建一个插点(图中红色指针 样式可以自己调整)
    if (!marker) {
      marker = new TMap.MultiMarker({
        id: 'marker-layer',
        map,
        styles: {
          marker: new TMap.MarkerStyle({
            width: 20,
            height: 35,
          }),
        },
        geometries: [
          {
            id: 'mapMarker',
            styleId: 'marker',
            position: clickPoint,
            properties: {
              title: 'marker',
            },
          },
        ],
      })
    }
    //如果已创建插点 则仅修改插点位置
    marker.setGeometries([
      {
        id: 'mapMarker',
        styleId: 'marker',
        position: clickPoint,
        properties: {
          title: 'marker',
        },
      },
    ])
   console.log('纬度='+lat,'经度='+lng)
  })
}

然后呢,经过一番讨论觉得这样不够智能,最终又决定换一个操作方式

案例2 绘制多边形

改版后的地图呢,支持自定义多边形,大概就是这个效果,其具体使用文档附在下方

image.png 腾讯地图似乎没写,要使用geometry的话要再额外引入一下 还是在index.html里

<script charset="utf-8" src="https://map.qq.com/api/gljs?libraries=tools&v=1.exp&key=申请到的key值"></script>

实现代码

function initMap() {
  // 定义地图中心点坐标
  const center = new window.TMap.LatLng(...mapCenter)
  // 定义map变量,调用 TMap.Map() 构造函数创建地图

  const map = new window.TMap.Map(document.getElementById('container'), {
    center, // 设置地图中心点坐标
    zoom: 8.5, // 设置地图缩放级别
    mapStyleId: 'style1', // 设置地图样式
  })
  // 多边形初始形状(点坐标)
  const simplePath = []
  //如果需要回显↓ defaultGeometry的值类似创建图形后返回的paths数组
  if (defaultGeometry) {
    defaultGeometry.forEach((item) => {
      simplePath.push(new TMap.LatLng(item.lat, item.lng))
    })
  }
  // 创建多边形 这里也可以直接放进editor里边创建
  const polygon = new TMap.MultiPolygon({
    map,
    geometries: [
      {
        paths: simplePath,
      },
    ],
  })
  // 编辑器工作模式
  const actionModeEnum = {
    DRAW: TMap.tools.constants.EDITOR_ACTION.DRAW, // 绘制模式,该模式下用户可绘制新图形
    INTERACT: TMap.tools.constants.EDITOR_ACTION.INTERACT, // 交互模式,该模式下用户可选中图形进行删除、修改
  }
  const actionType = simplePath.length ? 'INTERACT' : 'DRAW'
  // 创建编辑器
  editor = new window.TMap.tools.GeometryEditor({
    // TMap.tools.GeometryEditor 文档地址:https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocEditor
    map, // 编辑器绑定的地图对象
    overlayList: [
      // 可编辑图层 文档地址:https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocEditor#4
      {
        overlay: polygon,
        id: 'polygon',
      },
    ],
    actionMode: actionModeEnum[actionType],
    activeOverlayId: 'polygon', // 激活图层
    snappable: true, // 开启吸附
    selectable: true, // 开启选中 多边形可以进行操作
  })
  // 如果有回显多边形 则允许选中进行操作
  showDeleteIcon.value = simplePath.length
  // 监听绘制结束事件,获取绘制几何图形
  editor.on('draw_complete', (geometry) => {
  //id是图形创建时自动生成的唯一值
    const id = geometry.id
    //获取到刚创建的多边形
    const geo = polygon.geometries.filter((item) => {
      return item.id === id
    })
    // 绘制完成后不允许绘制第二个多边形 修改为交互模式 允许修改
    // 因为我的需求只允许绘制一个多边形 如果允许绘制多个多边形 下边这句不需要写
    editor.setActionMode(actionModeEnum.INTERACT)
    //多边形的点位数据(经纬度)
    console.log(geo[0].paths)
  })
  // 监听删除
  editor.on('delete_complete', (evtResult) => {
  //删除后修改模式为绘画
    editor.setActionMode(actionModeEnum.DRAW)
    //此处可以获取到被删除的多边形的信息
    console.log(evtResult)
  })
  // 编辑多边形
  editor.on('adjust_complete', (evtResult) => {
      console.log(evtResult.paths)
  })
  // 选中多边形
  editor.on('select', (evtResult) => {
      console.log(evtResult)
  })
}

因为我的地图是一个组件,需要配合element plus的dialog使用,引用地图组件时发现会报错,而后发现在initMap方法里先用一下await nextTick()就可以了

async function initMap() {
  await nextTick()
  ....功能代码
  }

结语

在腾讯地图的使用中我发现api文档似乎有些乱,每次搜索关键字出来的都不是同一个文档地址,也有可能是我不会正确使用腾讯地图的文档.
如果内容有不正确的地方或者有良好的建议请不吝赐教,能多给我点指导是最好了哈哈哈哈

circle文档地址 lbs.qq.com/javascript_…
GeometryEditor 文档地址:lbs.qq.com/webApi/java…
腾讯地图绘制几何图形文档lbs.qq.com/webDemoCent…
腾讯地图演示文档lbs.qq.com/webDemoCent…