Openlayers的交互功能(五)——删除图斑

  • 前面几篇文章已经对OpenLayers的交互和Draw控件的使用有了基本的了解,下面将对OpenLayers的图斑删除、编辑、平移、框选平移进行逐一介绍。

一、删除图斑

  • 图斑的删除是非常简单的,只要我们能获取到这个Feature,再将这个Feature从包含它的Source中移除就完成了删除功能。
  • 之前的文章介绍过使用OpenLayers点击事件选中图斑和使用Select控件选中图斑,在删除功能中,这两个方式都是可行的。

1、使用Select控件获取图斑并删除

  • 之前的文章已经介绍过Select控件的用法,如果对Select控件不了解的朋友可以查看这里

1.1 初始化Select控件

// 定义一个Select控件实例对象,并设置相关样式
let select = new Select({
  style: new Style({
    fill: new Fill({
      color: "rgba(255,0,0,0.5)",
    }),
    stroke: new Stroke({
      color: "rgba(0,0,255,1)",
    }),
  }),
});
// 将Select控件添加到地图中
map.addInteraction(select);

// 监听select选中事件
// 【注】:delFeature定义成了全局变量,这段只是截取出来的代码,所以没有包含delFeature的定义
select.on("select", (evt) => {
  delFeature = select.getFeatures().getArray();
});

1.2 初始化地图

/**
 * 为了方便其他函数调用地图和图层,把变量定义成全局的
 */
let map; // 地图
let vectorLayer; // 存放Feataure的图层
let delFeature; // 等待删除的图斑
let draw; // 绘制控件
let drawSource = new VectorSource(); // 绘制图层的数据源
let select; // 选中控件
/**
 * 初始化地图
 */
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:4326为坐标系定义地图的视图中心和缩放级别
    view: new View({
      projection: "EPSG:4326",
      center: [125.3574397847, 43.8865062907],
      zoom: 18,
    }),
  });
  // 添加面图层
  addLayer();
  // 选中事件
  select = new Select({
    style: new Style({
      fill: new Fill({
        color: "rgba(255,0,0,0.5)",
      }),
      stroke: new Stroke({
        color: "rgba(0,0,255,1)",
      }),
    }),
  });
  map.addInteraction(select);

  // 监听select选中事件
  select.on("select", (evt) => {
    delFeature = select.getFeatures().getArray();
  });
};

const addLayer = () => {
  vectorLayer = new VectorLayer({
    source: new VectorSource(),
  });
  vectorLayer.getSource().addFeature(
    // 添加面图层
    new Feature({
      geometry: new Polygon([
        [
          [125.3579180563, 43.888298024],
          [125.3587389704, 43.887798338],
          [125.3574397847, 43.8865062907],
          [125.3579180563, 43.888298024],
        ],
      ]),
    })
  );
  map.addLayer(vectorLayer);
  map.getView().setCenter([125.3579180563, 43.888298024]);
};

1.3 使用Select控件删除图斑

  • 上面的代码中,已经监听到了select事件选中的图斑,也就是delFeature,下面就可以通过这个Feature找到对应的Source,并将Feature从Source中删除。
  • 我在网页上新增了一个删除按钮,当用户选中图斑以后,再点击删除按钮就可以删除该图斑。
1.3.1 第一种情况

第一种情况是将Layer单独设置成全局变量,直接使用layer.getSource()方法获取到Source,然后删除该图斑

const delFeatures = () => {
  if (delFeature.length > 0) {
    vectorLayer.getSource().removeFeature(delFeature[0]);
  }
};
1.3.2 第二种情况

第二种情况是将Source单独设置成全局变量,直接使用source.removeFeature()就可以直接删除图斑。
其中,removeFeature()中要填写对应的Feature
【注】:本文没有为Source单独设置全局变量,下面代码中的vectorSource是假定Source的变量名。

const delFeatures = () => {
  if (delFeature.length > 0) {
    vectorSource.removeFeature(delFeature[0]);
  }
};
1.3.3 第三种情况

第三种情况只适用于Select,是Select控件自己的方法,鼠标事件无法使用。

const delFeatures = () => {
  if (delFeature.length > 0) {
    select.getLayer(delFeature[0]).getSource().removeFeature(delFeature[0]);
  }
};

2、使用鼠标单击事件删除图斑

  • 需要将最开始初始化地图的方法中初始化监听鼠标事件。

2.1 初始化鼠标单击事件

  // 地图监听事件
  map.on("singleclick", function (evt) {
    delFeature = map.getFeaturesAtPixel(evt.pixel);
  });

2.2 初始化地图的完整代码

/**
 * 为了方便其他函数调用地图和图层,把变量定义成全局的
 */
let map; // 地图
let vectorLayer; // 存放Feataure的图层
let delFeature; // 等待删除的图斑
let draw; // 绘制控件
let drawSource = new VectorSource(); // 绘制图层的数据源
let select; // 选中控件
/**
 * 初始化地图
 */
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:4326为坐标系定义地图的视图中心和缩放级别
    view: new View({
      projection: "EPSG:4326",
      center: [125.3574397847, 43.8865062907],
      zoom: 18,
    }),
  });
  // 固定添加点、线、面图层
  addLayer();
  // 地图监听事件
  map.on("singleclick", function (evt) {
    delFeature = map.getFeaturesAtPixel(evt.pixel);
  });
};

const addLayer = () => {
  vectorLayer = new VectorLayer({
    source: new VectorSource(),
  });
  vectorLayer.getSource().addFeature(
    // 添加面图层
    new Feature({
      geometry: new Polygon([
        [
          [125.3579180563, 43.888298024],
          [125.3587389704, 43.887798338],
          [125.3574397847, 43.8865062907],
          [125.3579180563, 43.888298024],
        ],
      ]),
    })
  );
  map.addLayer(vectorLayer);
  map.getView().setCenter([125.3579180563, 43.888298024]);
};

2.3 使用鼠标监听事件删除图斑

  • 这里的方法和上述Select控件删除图斑的前两种方法是一样的,不再进行赘述。
  • 但是需要注意的是,无法使用第三种方法。

3、完整代码

<template>
  <!-- 初始化一个地图容器 -->
  <div id="map"></div>
  <div style="position: absolute; right: 50px">
    <button @click="delFeatures()">删除</button>
    <!--      <button @click="addDraw('Point')">绘制点</button>-->
    <!--      <button @click="addDraw('LineString')">绘制线</button>-->
    <!--      <button @click="addDraw('Polygon')">绘制面</button>-->
    <!--      <button @click="addDraw('Circle')">绘制圆</button>-->
  </div>
</template>

<script setup>
// 引入需要的包
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 { Point, Polygon } from "ol/geom";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";

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

/**
 * 为了方便其他函数调用地图和图层,把变量定义成全局的
 */
let map; // 地图
let vectorLayer; // 存放Feataure的图层
let delFeature; // 等待删除的图斑
let draw; // 绘制控件
let drawSource = new VectorSource(); // 绘制图层的数据源
let select; // 选中控件
/**
 * 初始化地图
 */
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, // 缩放级别
    // }),

    // 以EPSG:4326为坐标系定义地图的视图中心和缩放级别
    view: new View({
      projection: "EPSG:4326",
      center: [125.3574397847, 43.8865062907],
      zoom: 18,
    }),
  });
  addLayer();

  // // 添加全屏控件
  // let fullScreen = new FullScreen()
  // map.addControl(fullScreen)
  //
  // // 比例尺控件
  // let scaleLine = new ScaleLine()
  // map.addControl(scaleLine)
  //
  // 地图监听事件
  // map.on("singleclick", function (evt) {
  //   delFeature = map.getFeaturesAtPixel(evt.pixel);
  //   // let pixel = map.getEventPixel(evt.originalEvent); //获取点击的像素点
  //   // let coordinate = map.getCoordinateFromPixel(pixel); //获取像素点的坐标
  //   // console.log(coordinate);
  // });

  // 选中事件
  select = new Select({
    style: new Style({
      fill: new Fill({
        color: "rgba(255,0,0,0.5)",
      }),
      stroke: new Stroke({
        color: "rgba(0,0,255,1)",
      }),
    }),
  });
  map.addInteraction(select);

  // 监听select选中事件
  select.on("select", (evt) => {
    delFeature = select.getFeatures().getArray();
  });
};

const addLayer = () => {
  vectorLayer = new VectorLayer({
    source: new VectorSource(),
  });
  vectorLayer.getSource().addFeature(
    // 添加点图层
    // new Feature({
    //   geometry: new Point([125.35, 43.88]),
    // })

    // // 添加线图层
    // new Feature({
    //   geometry: new LineString([
    //     [125.3579180563, 43.888298024],
    //     [125.3587389704, 43.887798338],
    //   ]),
    // }),

    // 添加面图层
    new Feature({
      geometry: new Polygon([
        [
          [125.3579180563, 43.888298024],
          [125.3587389704, 43.887798338],
          [125.3574397847, 43.8865062907],
          [125.3579180563, 43.888298024],
        ],
      ]),
    })
  );
  map.addLayer(vectorLayer);
  map.getView().setCenter([125.3579180563, 43.888298024]);
};

/**
 * 绘制功能
 * @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);
  });
};

const delFeatures = () => {
  if (delFeature.length > 0) {
    // vectorLayer.getSource().removeFeature(delFeature[0]);
    select.getLayer(delFeature[0]).getSource().removeFeature(delFeature[0]);
  }
};

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

<style scoped>
#map {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

:deep(.ol-attribution) {
  display: none;
}
</style>

3、实现效果

3.1 使用Select控件删除图斑

使用Select控件删除图斑

3.2 使用鼠标监听事件删除图斑

使用鼠标监听事件删除图斑

4、两种方法的对比

  • 可以看出,使用Select控件删除图斑时,可以高亮已经选中的图斑,能够清晰的展示出要删除的图斑。
  • 但是如果使用鼠标单击事件,可能会导致不知道是否已经正确选中图斑的情况发生。不过这种情况可以通过新增一个高亮图层,将已经选中的图斑clone进高亮图层中,在删除时,同时删除两个图层中的图斑。
  • 读者可以自行选择使用哪种方法。

二、结语

  • 本文对图斑的删除进行了简单的介绍,后续将继续更新Feature的平移、框选平移等操作。

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

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于使用C#和ArcGIS Engine来获取图层字段信息,可以按照以下步骤进行操作: 1. 首先,确保您已经安装了ArcGIS Engine并在项目中添加了相应的引用。 2. 创建一个ArcGIS Engine的地图控件对象,用于加载和显示地图数据。 3. 加载您需要获取字段信息的地图数据。可以使用AxMapControl对象的LoadMxFile方法加载地图文档文件,或者使用Open方法加载地图文件。 4. 获取要操作的图层对象。可以使用AxMapControl对象的get_Layer方法获取指定名称或索引的图层对象。 5. 通过强制转换图层对象为IFeatureLayer接口,以便访问图层的要素类信息。 6. 通过IFeatureLayer接口的FeatureClass属性获取图层的要素类对象。 7. 通过IFeatureClass接口的Fields属性获取要素类的字段集合。 8. 遍历字段集合,获取每个字段的相关信息,比如字段名、类型等。 下面是一个示例代码片段,展示了如何实现上述步骤: ```csharp using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Geodatabase; // 加载地图数据 axMapControl1.LoadMxFile("path_to_mx_file"); // 获取目标图层 ILayer layer = axMapControl1.get_Layer(layerIndex); IFeatureLayer featureLayer = (IFeatureLayer)layer; // 获取要素类对象 IFeatureClass featureClass = featureLayer.FeatureClass; // 获取字段集合 IFields fields = featureClass.Fields; // 遍历字段集合 for (int i = 0; i < fields.FieldCount; i++) { IField field = fields.get_Field(i); string fieldName = field.Name; esriFieldType fieldType = field.Type; // 打印字段信息 Console.WriteLine("字段名称:{0},字段类型:{1}", fieldName, fieldType); } ``` 请注意,以上代码仅为示例,您需要根据您的具体需求进行相应的修改和适配。 希望对您有帮助!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值