首页 > 编程语言 >Vue2+OpenLayers实现添加多边形覆盖物(提供Gitee源码)

Vue2+OpenLayers实现添加多边形覆盖物(提供Gitee源码)

时间:2025-01-17 20:57:06浏览次数:3  
标签:const 多边形 currentCoordinates Gitee 源码 OpenLayers coordinate new 绘制

目录

一、案例截图

二、安装OpenLayers库

三、代码实现

3.1、初始化变量

3.2、实现一个自定义面

3.3、创建多边形图层

3.4、创建点位

3.5、更新多边形显示

3.6、开始绘制/结束绘制

3.7、创建/更新虚线显示

3.8、初始化地图事件

3.9、完整代码

四、Gitee源码


一、案例截图

二、安装OpenLayers库

npm install ol

三、代码实现

代码相对来说可能会有点复杂,我已经把每行注释都写上了,这样方便大家更好去理解。

页面代码是这样的,很简单:

<div>
  <el-button @click="startDrawing" :disabled="startButton" type="primary">开始绘制</el-button>
  <el-button @click="endDrawing" :disabled="endButton" type="success">完成绘制</el-button>
  <div id="map-container"></div>
</div>

3.1、初始化变量

关键代码:

data() {
    return {
      map:null,
      drawing: false,
      //是否禁用开始绘制按钮
      startButton:false,
      //是否禁用结束绘制按钮
      endButton:true,
      //存放当前经纬度集合
      currentCoordinates: [],
      //图层多边形图层级
      vectorLayers: [],
      // 存储虚线图层
      lineLayer: null,
      // 存储虚线经纬度
      lineCoordinates:[],

    }
  },

3.2、实现一个自定义面

关键代码:

initBasePolygon() {
  // 定义多边形的坐标
  const coordinates = [
    [
      [120.430070,31.938140],
      [120.428570,31.939100],
      [120.429530,31.941680],
      [120.431240,31.943580],
      [120.432410,31.944820],
      [120.433600,31.943970],
    ]
  ];

  // 创建多边形对象
  const polygon = new Polygon(coordinates);

  // 创建特征
  const polygonFeature = new Feature(polygon);

  // 创建矢量图层并添加特征
  const vectorSource = new VectorSource({
    features: [polygonFeature]
  });

  const vectorLayer = new VectorLayer({
    source: vectorSource,
    style: new Style({
      fill: new Fill({
        color: 'rgba(255, 0, 0, 0.5)' // 填充颜色为红色
      }),
      stroke: new Stroke({
        color: '#ffcc33',
        width: 2
      })
    })
  });
  // 将矢量图层添加到地图中
  this.map.addLayer(vectorLayer);
},

3.3、创建多边形图层

每次点击开始绘制代表需要创建一个新的多边形图层,进行绘制。

关键代码:

//创建多边形图层
createPolygonLayer(coordinate) {
  //存放当前点经纬度信息
  this.currentCoordinates.push(coordinate);
  //存放当前虚线经纬度信息
  this.lineCoordinates.push(coordinate);
  //创建多边形对象
  const polygon = new Polygon([coordinate]);
  //创建特征存放多边形对象
  const polygonFeature = new Feature(polygon);
  //创建数据源用于存放多个特征
  const vectorSource = new VectorSource({
    features: [polygonFeature],
  });

  //将数据源添加到图层上
  const vectorLayer = new VectorLayer({
    source: vectorSource,
    style: new Style({
      fill: new Fill({
        color: 'rgba(255, 0, 0, 0.5)', // 填充颜色为红色
      }),
      stroke: new Stroke({
        color: '#ffcc33',
        width: 2,
      }),
    }),
  });
  this.map.addLayer(vectorLayer);
  this.vectorLayers.push(vectorLayer);
},

3.4、创建点位

关键代码:

//添加点
addPoint(coordinate) {
  //添加到当前经纬度集合
  this.currentCoordinates.push(coordinate);
  if (this.currentCoordinates.length > 2) {
    this.updatePolygon();
  }
},//添加点
addPoint(coordinate) {
  //添加到当前线经纬度集合
  this.lineCoordinates.push(coordinate);
  //添加到当前点经纬度集合
  this.currentCoordinates.push(coordinate);
  if (this.currentCoordinates.length > 2) {
    //更新多边形显示
    this.updatePolygon();
  }
},

3.5、更新多边形显示

关键代码:

//更新多边形显示
updatePolygon() {
  // 更新正在绘制的多边形
  const polygon = new Polygon([this.currentCoordinates]);
  if (this.vectorLayers.length > 0) {
    //因为一个图层只存放一个多边形特征,直接刷新它的经纬度信息
    this.vectorLayers[this.vectorLayers.length - 1].getSource().getFeatures()[0].setGeometry(polygon);
  }
},

3.6、开始绘制/结束绘制

关键代码:

//开始绘制
startDrawing(){
  this.drawing = true;
  //禁用开始绘制按钮
  this.startButton = true;
  //释放结束绘制按钮
  this.endButton = false;
},

//结束绘制
endDrawing(){
  this.drawing = false;
  //直接和第一个点进行闭合
  this.currentCoordinates.push(this.currentCoordinates[0]);
  //更新多边形绘制
  this.updatePolygon();
  //将当前点经纬度信息置空
  this.currentCoordinates = [];
  //将当前线经纬度信息置空
  this.lineCoordinates = [];
  // 清除虚线
  this.map.removeLayer(this.lineLayer);
  this.lineLayer = null;
  //释放开始绘制按钮
  this.startButton = false;
  //禁用结束绘制按钮
  this.endButton = true;
},

3.7、创建/更新虚线显示

关键代码

updateLine(coordinate) {
  if (this.lineLayer) {
    // 更新现有虚线的最后一个坐标
    this.lineCoordinates[this.lineCoordinates.length - 1] = coordinate; // 修改最后一点
    const lineString = new LineString(this.lineCoordinates);
    this.lineLayer.getSource().getFeatures()[0].setGeometry(lineString);
  } else {
    // 创建虚线图层
    this.lineLayer = new VectorLayer({
      source: new VectorSource({
        features: [new Feature(new LineString([coordinate]))],
      }),
      style: new Style({
        stroke: new Stroke({
          color: 'rgba(0, 0, 255, 1)', // 虚线颜色
          width: 2,
          lineDash: [10, 10] // 设置虚线样式
        }),
      }),
    });
    this.map.addLayer(this.lineLayer);
    this.lineCoordinates.push(coordinate);
  }
},

3.8、初始化地图事件

关键代码: 

//初始化地图点击事件
initMapClickEvent() {
  let _that = this;
  // 添加点击事件监听
  this.map.on('click', (event) => {
    if (this.drawing) {
      //如果第一次点击则新建一个图层
      if(_that.currentCoordinates.length <=0){
        _that.createPolygonLayer(event.coordinate)
      }else{
        //否则把点直接添加到当前图层上
        _that.addPoint(event.coordinate);
      }
    }
  });

  // 添加鼠标移动事件
  this.map.on('pointermove', (event) => {
    if (this.drawing) {
      //更新线的位置
      this.updateLine(event.coordinate);
    }
  });
},

3.9、完整代码

<template>
  <div>
    <el-button @click="startDrawing" :disabled="startButton" type="primary">开始绘制</el-button>
    <el-button @click="endDrawing" :disabled="endButton" type="success">完成绘制</el-button>
    <div id="map-container"></div>
  </div>

</template>
<script>
import { Map, View } from 'ol'
import { Tile as TileLayer } from 'ol/layer'
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent'
import { WMTS } from 'ol/source'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { defaults as defaultControls} from 'ol/control';
import { GeoJSON } from 'ol/format';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Feature } from 'ol';
import Polygon from 'ol/geom/Polygon';
import {Fill, Stroke, Style} from "ol/style";
import {LineString} from "ol/geom";

export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {
  resolutions[z] = size / Math.pow(2, z);
}

export default {
  data() {
    return {
      map:null,
      drawing: false,
      //是否禁用开始绘制按钮
      startButton:false,
      //是否禁用结束绘制按钮
      endButton:true,
      //存放当前经纬度集合
      currentCoordinates: [],
      //图层多边形图层级
      vectorLayers: [],
      // 存储虚线图层
      lineLayer: null,
      // 存储虚线经纬度
      lineCoordinates:[],

    }
  },
  mounted(){
    this.initMap() // 加载矢量底图
  },
  methods:{
    initMap() {
      const KEY = '你申请的KEY'

      this.map = new Map({
        target: 'map-container',
        layers: [
          // 底图
          new TileLayer({
            source: new WMTS({
              url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${KEY}`,
              layer: 'vec', // 矢量底图
              matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影
              style: "default",
              crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
              format: "tiles", //请求的图层格式,这里指定为瓦片格式
              wrapX: true, // 允许地图在 X 方向重复(环绕)
              tileGrid: new WMTSTileGrid({
                origin: getTopLeft(projectionExtent),
                resolutions: resolutions,
                matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
              })
            })
          }),
          // 标注
          new TileLayer({
            source: new WMTS({
              url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${KEY}`,
              layer: 'cva', //矢量注记
              matrixSet: 'c',
              style: "default",
              crossOrigin: 'anonymous',
              format: "tiles",
              wrapX: true,
              tileGrid: new WMTSTileGrid({
                origin: getTopLeft(projectionExtent),
                resolutions: resolutions,
                matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18','19']
              })
            })
          })
        ],
        view: new View({
          center: [120.430070,31.938140],
          projection: projection,
          zoom: 17,
          maxZoom: 19,
          minZoom: 1
        }),
        //加载控件到地图容器中
        controls: defaultControls({
          zoom: false,
          rotate: false,
          attribution: false
        })
      });
      //初始化地图点击事件
      this.initMapClickEvent();
      //初始化一个基本的面
      this.initBasePolygon();
    },
    //初始化一个基本的面
    initBasePolygon() {
      // 定义多边形的坐标
      const coordinates = [
        [
          [120.430070,31.938140],
          [120.428570,31.939100],
          [120.429530,31.941680],
          [120.431240,31.943580],
          [120.432410,31.944820],
          [120.433600,31.943970],
        ]
      ];

      // 创建多边形对象
      const polygon = new Polygon(coordinates);

      // 创建特征
      const polygonFeature = new Feature(polygon);

      // 创建矢量图层并添加特征
      const vectorSource = new VectorSource({
        features: [polygonFeature]
      });

      const vectorLayer = new VectorLayer({
        source: vectorSource,
        style: new Style({
          fill: new Fill({
            color: 'rgba(255, 0, 0, 0.5)' // 填充颜色为红色
          }),
          stroke: new Stroke({
            color: '#ffcc33',
            width: 2
          })
        })
      });
      // 将矢量图层添加到地图中
      this.map.addLayer(vectorLayer);
    },

    //初始化地图点击事件
    initMapClickEvent() {
      let _that = this;
      // 添加点击事件监听
      this.map.on('click', (event) => {
        if (this.drawing) {
          //如果第一次点击则新建一个图层
          if(_that.currentCoordinates.length <=0){
            _that.createPolygonLayer(event.coordinate)
          }else{
            //否则把点直接添加到当前图层上
            _that.addPoint(event.coordinate);
          }
        }
      });

      // 添加鼠标移动事件
      this.map.on('pointermove', (event) => {
        if (this.drawing) {
          //更新线的位置
          this.updateLine(event.coordinate);
        }
      });
    },
    //添加点
    addPoint(coordinate) {
      //添加到当前线经纬度集合
      this.lineCoordinates.push(coordinate);
      //添加到当前点经纬度集合
      this.currentCoordinates.push(coordinate);
      if (this.currentCoordinates.length > 2) {
        //更新多边形显示
        this.updatePolygon();
      }
    },
    //更新多边形显示
    updatePolygon() {
      // 更新正在绘制的多边形
      const polygon = new Polygon([this.currentCoordinates]);
      if (this.vectorLayers.length > 0) {
        //因为一个图层只存放一个多边形特征,直接刷新它的经纬度信息
        this.vectorLayers[this.vectorLayers.length - 1].getSource().getFeatures()[0].setGeometry(polygon);
      }
    },

    //开始绘制
    startDrawing(){
      this.drawing = true;
      //禁用开始绘制按钮
      this.startButton = true;
      //释放结束绘制按钮
      this.endButton = false;
    },

    //结束绘制
    endDrawing(){
      this.drawing = false;
      //直接和第一个点进行闭合
      this.currentCoordinates.push(this.currentCoordinates[0]);
      //更新多边形绘制
      this.updatePolygon();
      //将当前点经纬度信息置空
      this.currentCoordinates = [];
      //将当前线经纬度信息置空
      this.lineCoordinates = [];
      // 清除虚线
      this.map.removeLayer(this.lineLayer);
      this.lineLayer = null;
      //释放开始绘制按钮
      this.startButton = false;
      //禁用结束绘制按钮
      this.endButton = true;
    },

    //创建多边形图层
    createPolygonLayer(coordinate) {
      //存放当前点经纬度信息
      this.currentCoordinates.push(coordinate);
      //存放当前虚线经纬度信息
      this.lineCoordinates.push(coordinate);
      //创建多边形对象
      const polygon = new Polygon([coordinate]);
      //创建特征存放多边形对象
      const polygonFeature = new Feature(polygon);
      //创建数据源用于存放多个特征
      const vectorSource = new VectorSource({
        features: [polygonFeature],
      });

      //将数据源添加到图层上
      const vectorLayer = new VectorLayer({
        source: vectorSource,
        style: new Style({
          fill: new Fill({
            color: 'rgba(255, 0, 0, 0.5)', // 填充颜色为红色
          }),
          stroke: new Stroke({
            color: '#ffcc33',
            width: 2,
          }),
        }),
      });
      this.map.addLayer(vectorLayer);
      this.vectorLayers.push(vectorLayer);
    },
    updateLine(coordinate) {
      if (this.lineLayer) {
        // 更新现有虚线的最后一个坐标
        this.lineCoordinates[this.lineCoordinates.length - 1] = coordinate; // 修改最后一点
        const lineString = new LineString(this.lineCoordinates);
        this.lineLayer.getSource().getFeatures()[0].setGeometry(lineString);
      } else {
        // 创建虚线图层
        this.lineLayer = new VectorLayer({
          source: new VectorSource({
            features: [new Feature(new LineString([coordinate]))],
          }),
          style: new Style({
            stroke: new Stroke({
              color: 'rgba(0, 0, 255, 1)', // 虚线颜色
              width: 2,
              lineDash: [10, 10] // 设置虚线样式
            }),
          }),
        });
        this.map.addLayer(this.lineLayer);
        this.lineCoordinates.push(coordinate);
      }
    },
  },
}
</script>
<style scoped>
#map-container {
  width: 100%;
  height: 100vh;
}
</style>

四、Gitee源码

地址:Vue2+OpenLayers实现添加多边形覆盖物 

标签:const,多边形,currentCoordinates,Gitee,源码,OpenLayers,coordinate,new,绘制
From: https://blog.csdn.net/HJW_233/article/details/145213164

相关文章