高德地图jsApi的右键设置

890 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情

可视化的业务当中,除了我们熟悉的各种图标,柱状图、饼状图、折线图等等,地图这类也是可视化的重要的一部分,这部分要么使用百度要么使用高德,其API的学习成本还是比较高的,这一篇我们主要来看一下右键菜单的设置

注意:本文档中所有点位置信息和线信息都是虚构,无任何实际意义

  • 这一篇是本系列第三篇,前两篇大家可以点击链接访问
    高德地图jsApi的使用
    高德地图jsApi的点和线配置
    完成代码请查看代码仓库
    其实我在第一篇的代码中,已经把右键菜单的简单实现写上去了,不过没有写逻辑,都是官方的放大和缩小,大家可以看一下:
    (这里了不让传大图,这个效果大家看下面的下图吧)
    上面有两种右键,这点需要注意,高德的右键分为右键菜单和点标记右键,在我们点上面的右键 和地图上的右键是两种不同的设置方式,而基于这点,也更方便与我们来做交互,这一期我要实现的就是点击地图中第一个点,有选中和取消选中的选项,选中以后,点击第二个点,选择连接上一个点,可以将两个点进行连线,点击空白区域,则取消选中的点信息
  • 这一部分如果用框架来实现,比如 vuereact 可以做到保存状态,也就是选中一个点以后的状态,是比较简答的,而如果不使用框架,状态又该如何保存呢?大家可以先自己思考一下
    存储着一块大家可以自行发挥,因为我这个只是一个 demo , 所以并没有后端,正常项目中应该是和后端接口进行通信的,数据肯定是存储在数据库,那现在我们自己,可以不存储,直接使用代码完成,这样就是刷新以后不保存状态,也可以选择session存储,但是每次刷新都要存取,逻辑或增加很多,为了降低复杂度,我就直接代码搞了哦~

首先来看视图右键

Snipaste_2022-12-12_10-25-24.png 如图所示,这里没有点,直接在地图上搞的右键,这个右键我在业务中已经完成了,但是非点位的右键我现在只是需要一个功能,就是清除上次选中信息。

Snipaste_2022-12-12_11-23-16.png 这里只用小图了,大图应该不能通过~\

  • 这个功能实际上在我第一版代码中也有了,只不过没有加业务逻辑而已,这部分右键的功能在
    这里
  //创建右键菜单
  var menu = new ContextMenu(map);
  //自定义菜单类
  function ContextMenu(map)
  {
    var me = this;
    //地图中添加鼠标工具MouseTool插件
    this.mouseTool = new AMap.MouseTool(map);

    this.contextMenuPositon = null;
    var content = [];
    content.push("<div class='info context_menu'>");
    content.push("  <p onclick='menu.delMarkerMenu()'>移除上次选中信息</p>");
    content.push("</div>");
    //通过content自定义右键菜单内容
    this.contextMenu = new AMap.ContextMenu({ isCustom: true, content: content.join('') });

    //地图绑定鼠标右击事件——弹出右键菜单
    map.on('rightclick', function (e)
    {
      me.contextMenu.open(map, e.lnglat);
      me.contextMenuPositon = e.lnglat; //右键菜单位置
    });
  }
  ContextMenu.prototype.delMarkerMenu = function ()
  { 
    // 右键菜单上次选中点的信息
    clearPoint()
    this.mouseTool.close();
    this.contextMenu.close();
  };

接下来看点右键

Snipaste_2022-12-12_11-23-16.png

Snipaste_2022-12-12_11-30-18.png

Snipaste_2022-12-12_11-30-26.png
如上,实现的就是第一个点点击右键,选中,然后点位的样式样色有个变化,点击第二个点的时候,连线,如果在第二个点选择设置起点,则点位信息变化,刚才选择的点样式还原,如果点连线,没有选择起点,则给提示

Snipaste_2022-12-12_11-38-48.png

  • 在点上面的点击事件,这个点在高德上称之为覆盖物,所以我们在查找的时候,直接找覆盖物相关的就可以了,在 API 中便是覆盖物右键啦~

Snipaste_2022-12-12_11-42-01.png 这里有一些业务逻辑,就是操作点信息和存储点信息的逻辑,这点我做了抽离:

  // 存储当前选中点 DOM
  var currentPonit = '';
  // 当前选重点信息
  var currentData = {};
  // 修改DOM 类名
  function changeStyle(res,data){
    if(currentPonit !== ''){
      currentPonit.classList.remove('active');
    }
    currentPonit = res.children[0];
    currentData = data;
    currentPonit.classList.add('active');
  }
  // 清除点信息
  function clearPoint(){
    if(currentPonit){
      currentPonit.classList.remove('active');
    }
    currentPonit = "";
    currentData = {}
  }
  // 设置线信息
  function setLines(lnglat,color,weight){
    return new AMap.Polyline({
      path:lnglat,
      // showDir:true ,// 设置线方向
      strokeColor:color, // 线颜色
      strokeWeight: weight, // 线宽
      strokeOpacity:1 // 透明度
    })
  }
  • 然后覆盖物右键这里 需要给每个点位都添加,这相当于我们创建点位的时候,就添加了对应的事件侦听器~
coordData.forEach(function (marker)
  {
    //创建右键菜单
    var contextMenu = new AMap.ContextMenu();

    //右键放大
    contextMenu.addItem("放大一级", function ()
    {
      map.zoomIn();
    }, 0);

    //右键缩小
    contextMenu.addItem("缩小一级", function ()
    {
      map.zoomOut();
    },1);

    contextMenu.addItem("设置起点", function ()
    {
      console.log(marker,markerd.dom);
      changeStyle(markerd.dom,marker)
      contextMenu.close() // 关闭右键菜单
    });

    contextMenu.addItem("与起点连线", function ()
    {
      if(!currentPonit){
        alert('请选择起点')
        contextMenu.close() 
        return
      }else{
        // 这里其实可以根据数据判定线类型了,因为第二个选中点的信息和第一个选中点的信息都有了,但是过滤方法会比较复杂
        let path = [currentData.position,marker.position];
        const polyline1 = setLines(path,'#3366bb',5);
        map.add([polyline1]);
        clearPoint();
      }
      contextMenu.close() // 关闭右键菜单
    });
    let content = '<div class="marker-route"></div>';
    let markerd = new AMap.Marker(
    {
      map: map,
      // icon: marker?.icon,
      content,
      offset: new AMap.Pixel(-8,-8),
      visible:true, // 点标记是否可见
      position: [marker.position[0], marker.position[1]],
    });
  
    //绑定鼠标右击事件——弹出右键菜单
    markerd.on('rightclick', function (e)
    {
      contextMenu.open(map, e.lnglat);
    });
  });
  • 点位事件侦听这里,大家这一期可以思考一下,我们新增的点位应该如何来添加呢?

Snipaste_2022-12-12_11-48-40.png 之前是一个完整的数据坐标,在创建的时候直接侦听,这次新增一个点位,要添加我们这一期所有对应的事件和交互,应该怎么办? 下期就搞他!