Openlayers的交互功能(四)——利用Draw控件绘制图斑

  • 前面三篇文章已经对OpenLayers的基本情况以及图斑和图斑的选中有了基本的了解,下面将对OpenLayers的图斑绘制、删除、编辑、平移、框选平移进行逐一介绍。上述所有的功能都需要用到OpenLayers的Draw控件,那么本篇文章先对Draw控件进行介绍。

一、Draw控件概述

  • Draw控件是OpenLayers的Interaction中的类,负责勾绘交互,支持的绘制图斑类型包括Point(点)、LineString(线)、Polygon(面)和Circle(圆)。
  • 常用触发的事件包括drawstart和drawend,分别在绘制开始时(单击鼠标)和绘制结束时(双击鼠标)触发。还有一个平时用不到的触发事件drawabort,是在绘制中断的时候触发,使用情况较少。

二、Draw控件的常用参数

  • source:表示绘制完成的图斑放到哪个数据源中
  • type:表示绘制的要素是什么类型的,可选的有Point、LineString、Polygon、Circle
  • style:表示绘制的样式,如果没有设置样式,会使用上面Source对应的Layer的样式
  • clickTolerance:判断用户的行为是添加点,还是按住鼠标不松开进行拖拽地图。默认值是 6 像素,当按下鼠标和抬起鼠标左键之间的这段时间段内,如果地图被拖动没有超过 6 像素,那么默认为添加一个点,相反如果超过了 6 像素,那么不会添加点,只是平移一下地图。
  • snapTolerance:默认值是 12 像素。多边形第一个点和最后一个点的吸附判定范围。
  • minPoints:表示绘制单个要素最少的点数限制
  • maxPoints:表示绘制单个要素最多的点数限制
  • geometryName:设置绘制的要素的名称
  • condition:规定了什么情况下触发draw操作,默认不需要特殊条件进行触发。如果想要设置,可以参考OpenLayers官方文档中的Condition类
  • freehandCondition:规定了什么情况下触发不用多次点击绘制模式,也就是拖拽鼠标即可绘制要素的模式。默认是Shift按键。
  • wrapX:当地图水平显示多个相同位置时(缩放级别低的情况下会发生),是否显示多个勾绘任务。默认为false。

三、Draw控件的结束方式

  • 常用的结束绘制的方式主要是双击结束绘制,但是OpenLayers的双击鼠标事件默认是放大地图,所以当我们希望双击结束绘制的同时不放大地图的话,需要先将OpenLayers的默认事件移除,再给双击鼠标设置移除Draw控件。
  • 下面这段代码就可以移除OpenLayers默认的双击放大地图事件。
  // 移除双击缩放地图功能,使双击只用来结束绘制功能
  const dblClickInteraction = map
    .getInteractions()
    .getArray()
    .find((interaction) => {
      return interaction instanceof DoubleClickZoom;
    });
  map.removeInteraction(dblClickInteraction);
  • 下面这段代码会监听双击地图事件,当事件触发后,移除Draw控件,也就达到了停止绘制的目的。
  // 双击结束绘制
  map.on("dblclick", () => {
    map.removeInteraction(draw);
  });

四、Draw控件的监听事件

  • 常用的监听事件有drawstart和drawend,分别在绘制开始时触发和绘制结束时触发。

1. drawstart在绘制前触发

// 监听开始绘制事件
draw.on("drawstart", (evt) => {
  console.log("开始绘制");
  console.log(evt);
});

2. drawend在绘制结束后触发。需要注意的是,如果本次绘制失败,也就是没有产生图斑,那么drawend是监听不到任何事件的。

// 监听结束绘制事件
draw.on("drawend", (evt) => {
  console.log("结束绘制");
  console.log(evt);
});

3.监听事件输出的evt包含绘制的要素,也就是Feature。

Draw的监听事件

五、Draw控件的综合使用和完整代码

  • 在地图初始化后,通过点击按钮将Draw控件加入到地图当中,随后需要判断用户想要绘制什么类型的图斑,设置Draw控件的绘制方式。
// 将Draw控件加入到地图控件中
// [注]:本文将draw定义为全局变量,所以这里没有声明draw变量,可以在后续的全部代码中查看声明。
draw = new Draw({
  source: drawSource,
  type: type,
});
map.addInteraction(draw);
  • Vue中HTML代码如下:
<template>
  <!-- 初始化一个地图容器 -->
  <div id="map"></div>
  <div style="position: absolute; right: 50px">
    <button @click="addDraw('Point')">绘制点</button>
    <button @click="addDraw('LineString')">绘制线</button>
    <button @click="addDraw('Polygon')">绘制面</button>
    <button @click="addDraw('Circle')">绘制圆</button>
  </div>
</template>
  • Vue中JS代码如下:
// 引入需要的包
import TileLayer from "ol/layer/Tile";
import { OSM } from "ol/source";
import { Feature, View } from "ol";
import { Map } from "ol";
import { onMounted } from "vue";
import { Polygon } from "ol/geom";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";

import { Fill, Stroke, Style } from "ol/style";
import { DoubleClickZoom, Draw } from "ol/interaction";
import { fromLonLat } from "ol/proj";
import CircleStyle from "ol/style/Circle";

/**
 * 为了方便其他函数调用地图和图层,把变量定义成全局的
 */
let map; // 地图
let vectorLayer; // 存放Feataure的图层
let draw; // 绘制控件
let drawSource = new VectorSource(); // 绘制图层的数据源
/**
 * 初始化地图
 */
const initialMap = () => {
  map = new Map({
    target: "map", // 地图放到哪个容器中,值应该是div的id
    layers: [
      new TileLayer({
        source: new OSM(), // 加载OSM底图
      }),
      new VectorLayer({
        source: drawSource,
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)",
          }),
          stroke: new Stroke({
            // color: "#ffcc33",
            color: "#ff0033",
            width: 2,
          }),
          image: new CircleStyle({
            radius: 3,
            fill: new Fill({
              color: "#ffcc33",
            }),
          }),
        }),
      }),
    ],

    // 以EPSG:3857为坐标系定义地图的视图中心和缩放级别
    view: new View({
      projection: "EPSG:3857", // 坐标系
      // fromLonLat()是OpenLayers内置的函数,可以将一个坐标系转换成另一个坐标系。
      // 本文将EPSG:4326坐标系转成EPSG:3857坐标系
      center: fromLonLat([125.35, 43.88]), // 视图中心
      zoom: 18, // 缩放级别
    }),
};

/**
 * 绘制功能
 * @param type 想要绘制什么类型的图斑
 */
const addDraw = (type) => {
  draw = new Draw({
    source: drawSource,
    type: type,
  });
  map.addInteraction(draw);

  // 监听开始绘制事件
  draw.on("drawstart", (evt) => {
    console.log("开始绘制");
    console.log(evt);
  });

  // 监听结束绘制事件
  draw.on("drawend", (evt) => {
    console.log("结束绘制");
    console.log(evt);
  });

  // 移除双击缩放地图功能,使双击只用来结束绘制功能
  const dblClickInteraction = map
    .getInteractions()
    .getArray()
    .find((interaction) => {
      return interaction instanceof DoubleClickZoom;
    });
  map.removeInteraction(dblClickInteraction);

  // 双击结束绘制
  map.on("dblclick", () => {
    map.removeInteraction(draw);
  });
};

onMounted(() => {
  // 立即执行初始化地图函数
  initialMap();
});

六、结语

  • 本文对OpenLayers的Draw控件(绘制控件)进行了介绍,后续将继续更新Feature的删除、平移、框选平移等操作。

  • 如有错误,请批评指正!

  • 欢迎关注星林社区文章将同步更新在星林社区中!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值