openlayer+turfjs 图形交集、并集、差集

902 阅读1分钟

效果展示

mrea.gif

HTML

<template>
  <div>
    <div style="padding: 20px">
      <el-radio-group v-model="type" @change="typeChange">
        <el-radio
          :label="item.value"
          :key="item.value"
          v-for="item in options"
          >{{ item.label }}</el-radio
        >
      </el-radio-group>
    </div>
    <div id="featrues" class="dynamic-component-demo"></div>
    <div class="box_btn">
      <el-button type="primary" @click="commWay('intersect')">交集</el-button>
      <el-button type="success" @click="commWay('union')">并集</el-button>
      <el-button type="info" @click="commWay('difference')">差集</el-button>
    </div>
  </div>
</template>

VUE data 初始化

 data() {
    return {
      map: null,
      draw: null,
      type: "None",
      selectedArray: [],
      options: [
        { value: "None", label: "无" },
        { value: "Star", label: "五角星" },
        { value: "Spuare", label: "正方形" },
        { value: "Box", label: "长方形" },
        { value: "Regular", label: "正多边形" },
        { value: "fan", label: "扇形" },
      ],
    };
  },

公共常量

let source = new VectorSource({ wrapX: false }),
  vector = new VectorLayer({
    source,
    style: new Style({
      fill: new Fill({ color: "rgba(255,255,255,0.2)" }),
      stroke: new Stroke({ color: "#f00", width: 2 }),
      image: new CircleStyle({ radius: 7, fill: new Fill({ color: "#f00" }) }),
    }),
  });
const highlightStyle = new Style({
  fill: new Fill({
    color: "rgba(0,0,0,0.5)",
  }),
  stroke: new Stroke({
    color: "#67C23A",
    width: 2,
  }),
});

图形创建函数

详细代码和逻辑 见openlayers Draw 理解、特殊图形创建

初始化地图

    let map = new Map({
      // 设置地图图层
      layers: [gaodeMapLayer, vector],
      // 设置显示地图的视图
      view: new View({
        center: transform([104.065735, 30.659462], "EPSG:4326", "EPSG:3857"),
        zoom: 9,
        minZoom: 1,
        maxZoom: 21,
        //  projection: "EPSG:4326",
        rotation: 0,
      }),
      // 让id为map的div作为地图的容器
      target: "featrues",
      interactions: defaultInteractions({
        doubleClickZoom: false, // 取消双击放大功能交互
        // mouseWheelZoom: false, // 取消滚动鼠标中间的滑轮交互
        // shiftDragZoom: false, // 取消shift+wheel左键拖动交互
      }),
    });
    this.map = map;
    this.addInteraction();
    this.addEventListenerMAP(map);
  },
  methods:{
   addEventListenerMAP(map) {
      let _this = this;
      map.on("pointermove", (e) => {
        let pixel = map.getEventPixel(e.originalEvent);
        let hit = map.hasFeatureAtPixel(pixel);
        map.getTargetElement().style.cursor = hit ? "pointer" : "";
      });
      map.on("dblclick", function (e) {
        map.forEachFeatureAtPixel(e.pixel, function (f) {
          const selIndex = _this.selectedArray.indexOf(f);
          if (selIndex < 0) {
            _this.selectedArray.push(f);
            f.setStyle(highlightStyle);
          } else {
            _this.selectedArray.splice(selIndex, 1);
            f.setStyle(undefined);
          }
        });
      });
    },
  }

差集、并集、差集 实现代码

 methods: {
    commWay(key) {
      let { selectedArray } = this;
      if (selectedArray.length <= 1) {
        this.$message({
          message: "选择图形必须大于2个",
          type: "warning",
          showClose: true,
        });
        return;
      }
      let merge_feature = this.turfMethods([...selectedArray], key);
      if (merge_feature) {
        source = new VectorSource({
          wrapX: false,
          features: [merge_feature],
        });
        vector.setSource(source);
        this.selectedArray = [];
      }
    },
    turfMethods(selectedArray, key) {
      let Array_ = selectedArray,
        first = Array_.shift(),
        second = Array_.shift(),
        poly1 = turf.polygon(first.getGeometry().getCoordinates()),
        poly2 = turf.polygon(second.getGeometry().getCoordinates()),
        intersection = turf[key](poly1, poly2);
      if (Array_.length > 0) {
        return this.turfMethods(
          [new GeoJSON().readFeature(intersection), ...Array_],
          key
        );
      } else {
        if (intersection) {
          return new GeoJSON().readFeature(intersection);
        } else {
          this.$message({
            message: "图形没有交集",
            type: "warning",
            showClose: true,
          });
        }
      }
    },
  }