Vue2 + Openlayers 实现绘制、平移和框选平移功能

Vue2安装

本文不详细介绍Vue2的安装,具体可以参考这篇博客
Vue2安装

安装Openlayers

Openlayers有多种引用或安装方式,博主采用的是npm安装方式。

最新版本Openlayers安装

npm install -s ol

指定版本Openlayers安装

运行npm install -s ol后,找到package.json中的ol,将后面的版本号改成想要的版本,再运行npm install即可
本文采用的是5.3.3版本

其他方式安装可以参照Openlayers官网

Openlayers官网

初始化地图

使用Openlayers例子中的OSM地图。
Openlayers地图加载可以有很多参数,具体请看Openlayers官方API
博主使用的版本是5.3.3,但是官方文档看5.3.0的就可以

<script>

//引入
import Map from "ol/Map"
import {Tile as TileLayer} from "ol/layer";
import OSM from 'ol/source/OSM';
import View from "ol/View"
import {fromLonLat} from "ol/proj";

export default {
  name: "Map",
  data(){
    return {
      // 根据个人需求可以选择把数据不定义成全局的,但是有些功能需要全局变量,请读者自行斟酌
      map:{},  //地图容器,后续可能会涉及到map的相关操作,比如map.addLayer等,所以定义成全局的
  	  drawSource:new Vector(),	//绘制图层的数据源,后续某些功能可能会需要清空drawSource,所以定义成全局的
  	  //绘制功能初始化的地方,因为可能会需要用map.addInteraction()和map.removeInteraction(),所以定义成全局的
      draw :{}	
    }
  },
  methods:{
    //地图初始化方法
    initialMap(){
      //用that代替this,防止某些位置this指向发生变化
      let that = this
      that.map = new Map({
        target:"map", //挂载到id为map的div容器上
        layers:[
          new TileLayer({
            source: new OSM()	//OSM地图
          }),
          //绘制图层
          new VectorLayer({
            source:that.drawSource,	//数据源
            style: new Style({
              //图层样式
              fill: new Fill({
                color: "rgba(0, 0, 255, 0.2)", //填充颜色
              }),
              stroke: new Stroke({
                color: "#0000ff", //边框颜色
                width: 2, // 边框宽度
              }),
              image: new Circle({
                radius: 7,
                fill: new Fill({
                  color: "#0000ff",
                }),
              }),
            }),
          })
        ],
        //设置视图,包括中心点,坐标系,默认缩放级别,最大、最小缩放级别
        view: new View({
          projection:'EPSG:3857',	//坐标系
          center: fromLonLat([120.2,30.35]),	//中心点
          zoom: 10,	  //默认缩放级别
          minZoom:1,	//最小缩放级别
          maxZoom:18	//最大缩放级别
        })
      })
      console.log(that.map.getLayers())
    },

  },
  mounted() {
    this.initialMap()	//立即执行初始化地图方法
  }
}
</script>

绘制方法的实现

<script>

//引入
import Map from "ol/Map"
import {Tile as TileLayer, Vector as VectorLayer} from "ol/layer";
import OSM from 'ol/source/OSM';
import View from "ol/View"
import {fromLonLat} from "ol/proj";
import {DoubleClickZoom, Draw} from "ol/interaction";
import {Fill, Stroke, Style,Circle} from "ol/style";
import {Vector} from "ol/source"

export default {
  name: "Map",
  data(){
    return {
      map:{},  //地图容器,后续可能会涉及到map的相关操作,比如map.addLayer等,所以定义成全局的
      drawSource:new Vector(), //正常项目可能需要在其他函数中清空drawSource,所以定义成全局的
      drawVector:{}, //平移功能需要声明哪些图层可以被平移,所以定义成全局的
      draw :{}, //绘制功能,可能会在其他函数中使用this.map.removeInteraction(this.draw),所以定义成全局
    }
  },
  methods:{
    //地图初始化方法
    initialMap(){
      //用that代替this,防止某些位置this指向发生变化
      let that = this
      that.map = new Map({
        target:"map", //挂载到id为map的div容器上
        layers:[
          new TileLayer({
            source: new OSM()	//OSM地图
          }),
          that.drawVector = new VectorLayer({
            source:that.drawSource,
            style: new Style({
              //图层样式
              fill: new Fill({
                color: "rgba(0, 0, 255, 0.2)", //填充颜色
              }),
              stroke: new Stroke({
                color: "#0000ff", //边框颜色
                width: 2, // 边框宽度
              }),
              image: new Circle({
                radius: 7,
                fill: new Fill({
                  color: "#0000ff",
                }),
              }),
            }),
          })
        ],
        //设置视图,包括中心点,坐标系,默认缩放级别,最大、最小缩放级别
        view: new View({
          projection:'EPSG:3857',	//坐标系
          center: fromLonLat([120.2,30.35]),	//中心点
          zoom: 10,	  //默认缩放级别
          minZoom:1,	//最小缩放级别
          maxZoom:18	//最大缩放级别
        })
      })
      console.log(that.map.getLayers())
    },

    //绘制方法
    sketch() {
      let that = this;
      //移除双击缩放功能,使双击只用于关闭编辑状态
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction);

      //双击执行取消绘制
      that.map.on("dblclick", function () {
        that.MyDraw.setActive(false);
      });

      //初始化绘制交互
      that.draw = new Draw({
        //绘制对象
        source: that.drawSource, //绘制层数据源,勾绘的要素属于的数据集
        type: "Polygon",	//绘制的类型,这里绘制一个多边形,也可以是POINT(点)、LINE_STRING(线)、CIRCLE(圆)
        //设置一些样式
        style: new Style({
          fill: new Fill({
            color: "rgba(0,0,255,0.2)",
          }),
          stroke: new Stroke({
            color: "#0000ff",
            width: 2,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#0000ff",
            }),
          }),
        }),
      });
      // 加载交互绘制控件函数
      that.MyDraw = {
        //执行绘制函数的方法
        init: function () {
          that.map.addInteraction(that.draw);	//添加交互
          //绑定交互绘制工具开始绘制的事件
          that.draw.on("drawstart", function (evt) {
            //逻辑代码
          });
          //绑定交互绘制工具结束绘制的事件
          that.draw.on("drawend", function (evt) {
            //逻辑代码
            that.MyDraw.setActive(false); //绘制完毕以后关闭控件
          })
        },
        //控制控件开启或关闭的函数,active要传boolean类型
        /*
        * setActive()是Openlayers中Interaction的函数,作用是开启和关闭控件
        * 这里也可以不用setActive()函数,可以使用this.map.addInteraction()加载控件和this.map.removeInteraction()
        * 在绘制结束的时候移除控件。如果使用这种方法,就需要把map定义成全局的。
        */
        setActive: function (active) {
          that.draw.setActive(active); //激活控件
        },
      };
      that.MyDraw.init();	//执行绘制函数方法
    }
  },
  mounted() {
    this.initialMap()	//立即执行初始化地图方法
  }
}
</script>

上面的函数也可以写成另一种形式,效果都是一样的

    sketch2(){
      let that = this;
      //移除双击缩放功能,使双击只用于关闭编辑状态
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction);

      //双击执行取消绘制
      that.map.on("dblclick", function () {
        that.map.removeInteraction(that.draw)
      });

      //初始化绘制交互
      that.draw = new Draw({
        //绘制对象
        source: that.drawSource, //绘制层数据源,勾绘的要素属于的数据集
        type: "Polygon",	//绘制的类型,这里绘制一个多边形,也可以是POINT(点)、LINE_STRING(线)、CIRCLE(圆)
        //设置一些样式
        style: new Style({
          fill: new Fill({
            color: "rgba(0,0,255,0.2)",
          }),
          stroke: new Stroke({
            color: "#0000ff",
            width: 2,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#0000ff",
            }),
          }),
        }),
      });
      // 加载交互绘制控件函数
      (function initDraw() {
          that.map.addInteraction(that.draw);	//添加交互
          //绑定交互绘制工具开始绘制的事件
          that.draw.on("drawstart", function (evt) {
            //逻辑代码
          });
          //绑定交互绘制工具结束绘制的事件
          that.draw.on("drawend", function (evt) {
            //逻辑代码
          })
        })()
    }

效果展示
绘制功能展示

平移功能(拖拽功能)的实现

平移功能使用ol-ext实现
博主使用的版本是3.2.3,下面的方式是安装最新版的ol-ext,也可以使用开篇提到的方式更改成指定版本

npm install ol-ext

    //平移功能(拖拽功能)
    translation(){
      let that = this
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction); //移除双击缩放功能,使双击只用于关闭平移状态

      that.interactionDrag = new ExtTransform({
        enableRotatedTransform: false, //地图旋转时启用变换
        hitTolerance: 2,  //偏移量
        translate: true, // 拖拽
        stretch: false, // 拉伸
        scale: false, // 缩放
        rotate: false, // 旋转
        translateFeature: false, //显示中心位置
        noFlip: false, //防止特征几何翻转,默认为 false
        layers: [that.drawVector], //指定可以拖拽的图层
      });
      //添加交互
      that.map.addInteraction(that.interactionDrag);

      that.interactionDrag.on(["translatestart"], function (evt) {
      });
      that.interactionDrag.on(["translating"], function (evt) {
            //逻辑代码
          }
      );
      that.interactionDrag.on(["translateend"], function (evt) {
            //逻辑代码
          }
      );
      that.map.on("dblclick",function (){
        //双击移除控件,不再平移
        that.map.removeInteraction(that.interactionDrag)
      })
    }

框选平移功能的实现

    //框选平移
    boxSelectAndMove() {
      let that = this;
      //移除双击缩放功能,使双击只用于关闭编辑状态
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction);

      // 创建绘制矩形工具
      let drawBox = new Draw({
        source: new Vector(),
        type: 'Circle', //绘制的图形是圆形
        //官网描述geometryFunction:
        //将坐标数组和可选的现有几何图形和投影作为参数并返回几何图形的函数。
        //可选的现有几何是在没有第二个参数的情况下调用函数时返回的几何。
        geometryFunction: createBox(),  //将圆形改成矩形框,如果没有这行代码绘制出来的框会变成圆形
        //设置一些样式
        style: new Style({
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "rgba(255, 128, 0,1)",
            }),
          }),
          fill: new Fill({
            color: "rgba(1, 92, 199,0.1)",
          }),
          stroke: new Stroke({
            color: "rgba(56, 239, 255,1)",
            width: 1
          })
        })
      });
      that.map.addInteraction(drawBox) //添加交互
      let myTransform = {} //定义一个接收初始化框选平移的变量,后面需要双击的时候移除交互,所以定义在这里
      drawBox.on('drawstart', function (evt) {
        //逻辑代码
      })

      drawBox.on('drawend', function (evt) {
        let polygon = evt.feature.getGeometry() // 用polygon存储画出来的矩形框的信息,包括坐标等
        let features = that.drawSource.getFeatures() //取出所有要素,每一个都要判断是否相交
        let needToMoveFeatures = [] //相交的要素存在这里
        let isIntersect = false // 是否相交
        for(let i=0;i<features.length;i++){
          let coordinates = features[i].values_.geometry.flatCoordinates
          for(let j=0;j<coordinates.length;j+=2){
            // containsXY()是Openlayers的内置函数,可以判断点是否在多边形内。
            // 这里的应用是判断每一个feature的顶点是否在polygon内
            // 因为画的是矩形框,如果框选到了feature,那么这个feature的某一个顶点一定在矩形框内
            // 如果是其他逻辑,需要参照Openlayers官方文档使用其他方法
            if(polygon.containsXY(coordinates[j], coordinates[j + 1])){
              // 如果已经判断相交,直接跳出循环即可
              isIntersect = true
              needToMoveFeatures.push(features[i])
              break
            }
          }
        }
        if(isIntersect){
          that.map.removeInteraction(drawBox)
          // 这里不再写注释了,和平移功能的实现是一样的
          myTransform = new ExtTransform({
            enableRotatedTransform: false,
            layers: [that.drawVector],
            hitTolerance: 2,
            scale: false,
            rotate: false,
            keepAspectRatio: false,
            keepRectangle: false,
            translate: true,
            translateFeature: false,
            noFlip: false,
            stretch: false,
          })
          that.map.addInteraction(myTransform)  //添加控件
          myTransform.setSelection(needToMoveFeatures) //ol-ext中transform函数,可以直接把所有框选的要素当成一个整体

          myTransform.on('translatestart',function (evt){
            //逻辑代码
          })

          myTransform.on('translating',function (evt){
            //逻辑代码
          })

          myTransform.on('translateend',function (evt){
            //逻辑代码
            console.log(evt)
            //这里的evt包含了平移结束以后的feature信息,具体信息见下图
          })
        }
      })

      that.map.on('dblclick', function () {
        that.map.removeInteraction(drawBox)
        that.map.removeInteraction(myTransform)
      })
    },

效果展示
框选平移的实现

框选平移详细介绍

绘制两个图形

绘制了两个要素,一个是四边形,一个是六边形。
由于两个要素都是polygon类型的,所以四边形的要素坐标会显示5个,第一个和第五个是一样的。同理,六边形的坐标会显示7个,第一个和第七个也是一样的。
坐标系有两种情况,一种是一对一对的出现,另一种就是我后面截图上显示的情况,也就是横坐标和纵坐标是分开显示的

绘制了两个要素
控制台状态

我在绘制完成后(drawend事件的回调函数里)输出了evt,可以看到两个要素的具体信息

四边形要素具体信息
六边形要素具体信息
框选平移结束后的信息

框选平移结束事件后(translateend的回调函数中),我输出了evt,可以在这里面看到移动后要素的信息。
这里需要注意的是,看的是oldgeoms里面的信息。

框选平移结束后信息

可以根据不同需求,获取不同的信息。
这种方式是在框选平移结束后就需要要素的信息时使用,如果需要在别的函数里面获取新的要素信息,可以直接使用source.getFeatures()函数,就可以查看到最新的要素信息。
比如我这里就应该是this.drawSource.getFeatures()
这就需要把source定义成全局变量。

清空功能的实现

清空功能就不再赘述了,根据需求进行清空即可。记得清空source

    clear(){
      //只写了最简单的,根据需求增加即可
      this.drawSource.clear()
    },

注意事项

最好把每个交互都设置成全局变量,在执行每个函数之前都要移除一下交互,比如在执行平移的时候,要移除绘制的交互。

这样做可以避免用户在点击添加后发现自己点错了,又去点击平移,会导致两个函数都在执行,又绘制又平移,可能会出现错误。

项目源码

<template>
  <div>
    <div id="map">
    </div>
    <div class="Cards">
      <Card style="margin-top: 8px; width: 250px; z-index: 5">
        <Row>
          <Button style="margin-right: 6px; width:100px;" type="success" @click="sketch">
            <Icon type="md-add"/>
            添加
          </Button>
          <Button style="margin-right: 6px; width:100px;" type="error" @click="clear">
            <Icon type="md-close" />
            清空
          </Button>
        </Row>
          <Row style="margin-top: 4px;">
            <Button style="margin-right: 6px; width:100px;" type="info" @click="translation">
              <Icon type="md-move"/>
              平移
            </Button>
            <Button style="margin-right: 6px; width:100px;" type="warning" @click="boxSelectAndMove()">
              <Icon type="md-move"/>
              框选平移
            </Button>
        </Row>
      </Card>
    </div>
  </div>
</template>

<script>

//引入
import Map from "ol/Map"
import {Tile as TileLayer, Vector as VectorLayer} from "ol/layer";
import OSM from 'ol/source/OSM';
import View from "ol/View"
import {fromLonLat} from "ol/proj";
import {DoubleClickZoom, Draw} from "ol/interaction";
import {Fill, Stroke, Style,Circle} from "ol/style";
import {Vector} from "ol/source"
import ExtTransform from "ol-ext/interaction/Transform"
import {unByKey} from "ol/Observable";
import {GeoJSON} from "ol/format";
import {createBox} from "ol/interaction/Draw";

export default {
  name: "Map",
  data(){
    return {
      map:{},  //地图容器,后续可能会涉及到map的相关操作,比如map.addLayer等,所以定义成全局的
      drawSource:new Vector(), //正常项目可能需要在其他函数中清空drawSource,所以定义成全局的
      drawVector:{}, //平移功能需要声明哪些图层可以被平移,所以定义成全局的
      draw :{}, //绘制功能,可能会在其他函数中使用this.map.removeInteraction(this.draw),所以定义成全局
    }
  },
  methods:{
    //地图初始化方法
    initialMap(){
      //用that代替this,防止某些位置this指向发生变化
      let that = this
      that.map = new Map({
        target:"map", //挂载到id为map的div容器上
        layers:[
          new TileLayer({
            source: new OSM()	//OSM地图
          }),
          that.drawVector = new VectorLayer({
            source:that.drawSource,
            style: new Style({
              //图层样式
              fill: new Fill({
                color: "rgba(0, 0, 255, 0.2)", //填充颜色
              }),
              stroke: new Stroke({
                color: "#0000ff", //边框颜色
                width: 2, // 边框宽度
              }),
              image: new Circle({
                radius: 7,
                fill: new Fill({
                  color: "#0000ff",
                }),
              }),
            }),
          })
        ],
        //设置视图,包括中心点,坐标系,默认缩放级别,最大、最小缩放级别
        view: new View({
          projection:'EPSG:3857',	//坐标系
          center: fromLonLat([120.2,30.35]),	//中心点
          zoom: 10,	  //默认缩放级别
          minZoom:1,	//最小缩放级别
          maxZoom:18	//最大缩放级别
        })
      })
    },

    //绘制方法
    sketch() {
      let that = this;
      
      that.map.removeInteraction(that.draw)
      that.map.removeInteraction(that.interactionDrag)

      //移除双击缩放功能,使双击只用于关闭编辑状态
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction);

      //双击执行取消绘制
      that.map.on("dblclick", function () {
        that.MyDraw.setActive(false);
        that.map.removeInteraction(that.draw)
      });

      //初始化绘制交互
      that.draw = new Draw({
        //绘制对象
        source: that.drawSource, //绘制层数据源,勾绘的要素属于的数据集
        type: "Polygon",	//绘制的类型,这里绘制一个多边形,也可以是POINT(点)、LINE_STRING(线)、CIRCLE(圆)
        //设置一些样式
        style: new Style({
          fill: new Fill({
            color: "rgba(0,0,255,0.2)",
          }),
          stroke: new Stroke({
            color: "#0000ff",
            width: 2,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#0000ff",
            }),
          }),
        }),
      });
      // 加载交互绘制控件函数
      that.MyDraw = {
        //执行绘制函数的方法
        init: function () {
          that.map.addInteraction(that.draw);	//添加交互
          //绑定交互绘制工具开始绘制的事件
          that.draw.on("drawstart", function (evt) {
            //逻辑代码
          });
          //绑定交互绘制工具结束绘制的事件
          that.draw.on("drawend", function (evt) {
            //逻辑代码
            that.MyDraw.setActive(false); //绘制完毕以后关闭控件
            console.log(evt)
          })
        },
        //控制控件开启或关闭的函数,active要传boolean类型
        /*
        * setActive()是Openlayers中Interaction的函数,作用是开启和关闭控件
        * 这里也可以不用setActive()函数,可以使用this.map.addInteraction()加载控件和this.map.removeInteraction()
        * 在绘制结束的时候移除控件。如果使用这种方法,就需要把map定义成全局的。
        */
        setActive: function (active) {
          that.draw.setActive(active); //激活控件
        },
      };
      that.MyDraw.init();	//执行绘制函数方法
    },

    //第二种绘制方法
    sketch2(){
      let that = this;
      //移除双击缩放功能,使双击只用于关闭编辑状态
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction);

      //双击执行取消绘制
      that.map.on("dblclick", function () {
        that.map.removeInteraction(that.draw)
      });

      //初始化绘制交互
      that.draw = new Draw({
        //绘制对象
        source: that.drawSource, //绘制层数据源,勾绘的要素属于的数据集
        type: "Polygon",	//绘制的类型,这里绘制一个多边形,也可以是POINT(点)、LINE_STRING(线)、CIRCLE(圆)
        //设置一些样式
        style: new Style({
          fill: new Fill({
            color: "rgba(0,0,255,0.2)",
          }),
          stroke: new Stroke({
            color: "#0000ff",
            width: 2,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#0000ff",
            }),
          }),
        }),
      });
      // 加载交互绘制控件函数
      (function initDraw() {
          that.map.addInteraction(that.draw);	//添加交互
          //绑定交互绘制工具开始绘制的事件
          that.draw.on("drawstart", function (evt) {
            //逻辑代码
          });
          //绑定交互绘制工具结束绘制的事件
          that.draw.on("drawend", function (evt) {
            //逻辑代码
          })
        })()
    },

    //清空
    clear(){
      this.drawSource.clear()
    },

    //平移功能(拖拽功能)
    translation(){
      let that = this
      that.map.removeInteraction(that.draw)
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction); //移除双击缩放功能,使双击只用于关闭编辑状态

      that.interactionDrag = new ExtTransform({
        enableRotatedTransform: false,
        hitTolerance: 2,  //偏移量
        translate: true, // 拖拽
        stretch: false, // 拉伸
        scale: false, // 缩放
        rotate: false, // 旋转
        translateFeature: false, //显示中心位置
        noFlip: false, //防止特征几何翻转,默认为 false
        layers: [that.drawVector], //指定可以拖拽的图层
      });
      //添加交互
      that.map.addInteraction(that.interactionDrag);

      that.interactionDrag.on(["translatestart"], function (evt) {
      });
      that.interactionDrag.on(["translating"], function (evt) {
            //逻辑代码
          }
      );
      that.interactionDrag.on(["translateend"], function (evt) {
            //逻辑代码
          }
      );
      that.map.on("dblclick",function (){
        //双击移除控件,不再平移
        that.map.removeInteraction(that.interactionDrag)
      })
    },

    //框选平移
    boxSelectAndMove() {
      let that = this;

      that.map.removeInteraction(that.draw)
      that.map.removeInteraction(that.interactionDrag)

      //移除双击缩放功能,使双击只用于关闭编辑状态
      const dblClickInteraction = that.map
          .getInteractions()
          .getArray()
          .find((interaction) => {
            return interaction instanceof DoubleClickZoom;
          });
      that.map.removeInteraction(dblClickInteraction);

      // 创建绘制矩形工具
      let drawBox = new Draw({
        source: new Vector(),
        type: 'Circle', //绘制的图形是圆形
        //将坐标数组和可选的现有几何图形和投影作为参数并返回几何图形的函数。可选的现有几何是在没有第二个参数的情况下调用函数时返回的几何。
        geometryFunction: createBox(),  //将圆形改成矩形框,如果没有这行代码绘制出来的框会变成圆形
        //设置一些样式
        style: new Style({
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "rgba(255, 128, 0,1)",
            }),
          }),
          fill: new Fill({
            color: "rgba(1, 92, 199,0.1)",
          }),
          stroke: new Stroke({
            color: "rgba(56, 239, 255,1)",
            width: 1
          })
        })
      });
      that.map.addInteraction(drawBox) //添加交互
      let myTransform = {} //定义一个接收初始化框选平移的变量,后面需要双击的时候移除交互,所以定义在这里
      drawBox.on('drawstart', function (evt) {
        //逻辑代码
      })

      drawBox.on('drawend', function (evt) {
        let polygon = evt.feature.getGeometry() // 用polygon存储画出来的矩形框的信息,包括坐标等
        let features = that.drawSource.getFeatures() //取出所有要素,每一个都要判断是否相交
        let needToMoveFeatures = [] //相交的要素存在这里
        let isIntersect = false // 是否相交
        for(let i=0;i<features.length;i++){
          let coordinates = features[i].values_.geometry.flatCoordinates
          for(let j=0;j<coordinates.length;j+=2){
            // containsXY()是Openlayers的内置函数,可以判断点是否在多边形内。
            // 这里的应用是判断每一个feature的顶点是否在polygon内
            // 因为画的是矩形框,如果框选到了feature,那么这个feature的某一个顶点一定在矩形框内
            // 如果是其他逻辑,需要参照Openlayers官方文档使用其他方法
            if(polygon.containsXY(coordinates[j], coordinates[j + 1])){
              // 如果已经判断相交,直接跳出循环即可
              isIntersect = true
              needToMoveFeatures.push(features[i])
              break
            }
          }
        }
        if(isIntersect){
          that.map.removeInteraction(drawBox)
          // 这里不再写注释了,和平移功能的实现是一样的
          myTransform = new ExtTransform({
            enableRotatedTransform: false,
            layers: [that.drawVector],
            hitTolerance: 2,
            scale: false,
            rotate: false,
            keepAspectRatio: false,
            keepRectangle: false,
            translate: true,
            translateFeature: false,
            noFlip: false,
            stretch: false,
          })
          that.map.addInteraction(myTransform)  //添加控件
          myTransform.setSelection(needToMoveFeatures) //ol-ext中transform函数,可以直接把所有框选的要素当成一个整体

          myTransform.on('translatestart',function (evt){
            //逻辑代码
          })

          myTransform.on('translating',function (evt){
            //逻辑代码
          })

          myTransform.on('translateend',function (evt){
            //逻辑代码
            console.log(evt)
            //这里的evt包含了平移结束以后的feature信息,具体信息见下图
          })
        }
      })

      that.map.on('dblclick', function () {
        that.map.removeInteraction(drawBox)
        that.map.removeInteraction(myTransform)
      })
    },

  },
  mounted() {
    this.initialMap()	//立即执行初始化地图方法
  }
}
</script>

<style scoped>
  #map{
    width: 100%;
    height: 100%;
    position: absolute;
  }
  .Cards{
    position: absolute;
    top: 0%;
    right: 10%;
  }
</style>

博主第一次写文,如果写的不好请多多担待,有哪里写错了,也请大家批评斧正!感谢各位的支持!

Logo

前往低代码交流专区

更多推荐