【GeoJSON在线编辑平台】(1)创建地图+要素绘制+折点编辑+拖拽移动

前言

简单实现一下地图加载、要素绘制、折点编辑和拖拽移动。打算统一都写到一个类里面。

为了快速实现,直接去参考了官方案例。

创建地图

bash 复制代码
pnpm install ol

加载地图

在这里,我们创建一个 mapView.js 的文件专门用来放地图和视图相关的方法,需要时引用即可。

js 复制代码
/*
 * @Date: 2024-10-31 16:17:31
 * @LastEditors: ReBeX  cswwwx@gmail.com
 * @LastEditTime: 2024-11-04 11:24:42
 * @FilePath: \geojson-editor-ol\src\utils\mapView.js
 * @Description: 地图及视图相关方法
 * @Reference: https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html
 */

import TileLayer from 'ol/layer/Tile.js'
import Map from 'ol/Map.js'
import { get } from 'ol/proj.js'
import OSM from 'ol/source/OSM.js'
import View from 'ol/View.js'
import 'ol/ol.css'

/**
 * @description: 地图:简易初始化
 * @return {*}
 */
export function initMap() {
  const map = new Map({
    target: 'map',
    controls: [],
    view: new View({
      center: [0, 0],
      zoom: 1,
      extent: get('EPSG:3857').getExtent(),
    }),
    layers: [
      new TileLayer({
        source: new OSM(),
      }),
    ],
  })

  return map
}

实现绘制

代码参考自官方案例:https://openlayers.org/en/latest/examples/?q=draw

js 复制代码
import { Draw } from 'ol/interaction.js'
import { createBox, createRegularPolygon } from 'ol/interaction/Draw.js'
import { Vector as VectorLayer } from 'ol/layer.js'
import { Vector as VectorSource } from 'ol/source.js'

/**
 * @description: 矢量编辑类
 * @function: init 初始化
 * @function: draw 绘制
 * @function: stopDraw 停止绘制
 * @return {*}
 */
export class VectorEditor {
  map = null // 地图实例
  _source = null // 数据源
  _vector = null // 图层
  _draw = null // 绘制交互

  constructor(map) {
    this.map = map // 引入地图实例
    this.init()
  }

  // 操作:初始化
  init() {
    this._source = new VectorSource()
    this._vector = new VectorLayer({
      source: this._source,
    })
    this.map.addLayer(this._vector)

    this.stopDraw() // 停止绘制
  }

  // 操作:绘制
  // Options: 'Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'Circle', 'Square', 'Box'
  draw(type) {
    this.stopDraw() // 停止绘制

    let value = type // 绘制类型
    let geometryFunction = null

    switch (type) {
      case 'Square':
        value = 'Circle'
        geometryFunction = createRegularPolygon(4)
        break
      case 'Box':
        value = 'Circle'
        geometryFunction = createBox()
        break
    }

    this._draw = new Draw({
      source: this._source,
      type: value,
      geometryFunction, // 绘制回调
    })

    this.map.addInteraction(this._draw)
  }

  // 复位:停止绘制
  stopDraw() {
    this.map.removeInteraction(this._draw)
  }
}

使用方法:

js 复制代码
let drawVector = new VectorEditor(map) // 初始化绘制实例

drawVector.draw('Polygon') // 开始绘制

折点编辑

参考官方案例:https://openlayers.org/en/latest/examples/snap.html

简单来讲就是引入 SelectModify ,直接对上面代码的基础上进行完善:

js 复制代码
import { Draw, Modify, Select } from 'ol/interaction.js'
import { createBox, createRegularPolygon } from 'ol/interaction/Draw.js'
import { Vector as VectorLayer } from 'ol/layer.js'
import { Vector as VectorSource } from 'ol/source.js'

/**
 * @description: 矢量编辑类
 * @function: init 初始化
 * @function: draw 绘制
 * @function: watch 监听
 * @function: modify 修改
 * @function: stopDraw 停止绘制
 * @return {*}
 */
export class VectorEditor {
  map = null // 地图实例
  _source = null // 数据源
  _vector = null // 图层
  _draw = null // 绘制交互
  _select = null // 选择交互
  _modify = null // 修改交互

  constructor(map) {
    this.map = map // 引入地图实例
    this.init()
  }

  // 操作:初始化
  init() {
    this._source = new VectorSource()
    this._vector = new VectorLayer({
      source: this._source,
    })
    this.map.addLayer(this._vector)

    this._select = new Select() // 实例化选择交互
    this._modify = new Modify({ // 实例化修改交互
      features: this._select.getFeatures(),
    })

    this.map.addInteraction(this._modify)
    this.map.addInteraction(this._select)
    this.stopDraw()
    this.watch()
  }

  // 监听:各类事件
  watch() {
    // 事件:选择状态改变时清空已选择的要素
    this._select.on('change:active', () => {
      this._select.getFeatures().forEach((item) => {
        this._select.getFeatures().remove(item)
      })
    })
  }

  // 操作:绘制
  // Options: 'Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'Circle', 'Square', 'Box'
  draw(type) {
    this.stopDraw() // 停止绘制

    let value = type // 绘制类型
    let geometryFunction = null

    switch (type) {
      case 'Square':
        value = 'Circle'
        geometryFunction = createRegularPolygon(4)
        break
      case 'Box':
        value = 'Circle'
        geometryFunction = createBox()
        break
    }

    this._draw = new Draw({
      source: this._source,
      type: value,
      geometryFunction, // 绘制回调
    })

    this.map.addInteraction(this._draw)
  }

  // 复位:停止绘制
  stopDraw() {
    this.map.removeInteraction(this._draw)
    this._modify.setActive(false)
    this._select.setActive(false)
  }

  // 操作:修改
  modify(flag = true) {
    this.stopDraw()

    this._select.setActive(flag)
    this._modify.setActive(flag)
  }
}

使用方法:

js 复制代码
let drawVector = new VectorEditor(map) // 初始化绘制实例

drawVector.modify() // 编辑

拖拽移动

参考官方案例:https://openlayers.org/en/latest/examples/translate-features.html

这次是引入 Translate

js 复制代码
/*
 * @Date: 2024-11-04 13:46:37
 * @LastEditors: ReBeX  cswwwx@gmail.com
 * @LastEditTime: 2024-11-04 15:56:23
 * @FilePath: \geojson-editor-ol\src\utils\vectorEditor.js
 * @Description: 矢量编辑相关功能
 */
 
import { Draw, Modify, Select, Translate } from 'ol/interaction.js'
import { createBox, createRegularPolygon } from 'ol/interaction/Draw.js'
import { Vector as VectorLayer } from 'ol/layer.js'
import { Vector as VectorSource } from 'ol/source.js'

/**
 * @description: 矢量编辑类
 * @function: init 初始化
 * @function: draw 绘制
 * @function: watch 监听
 * @function: modify 修改
 * @function: translate 移动
 * @function: stopDraw 停止绘制
 * @return {*}
 */
export class VectorEditor {
  map = null // 地图实例
  _source = null // 数据源
  _vector = null // 图层
  _draw = null // 绘制交互
  _select = null // 选择交互
  _modify = null // 修改交互
  _translate = null // 拖拽交互

  constructor(map) {
    this.map = map // 引入地图实例
    this.init()
  }

  // 操作:初始化
  init() {
    this._source = new VectorSource()
    this._vector = new VectorLayer({
      source: this._source,
    })
    this.map.addLayer(this._vector)

    this._select = new Select() // 实例化选择交互
    this._modify = new Modify({ // 实例化修改交互
      features: this._select.getFeatures(),
    })
    this._translate = new Translate({
      features: this._select.getFeatures(),
    })

    this.map.addInteraction(this._modify)
    this.map.addInteraction(this._select)
    this.map.addInteraction(this._translate)

    this.stopDraw()
    this.watch()
  }

  // 监听:各类事件
  watch() {
    // 事件:选择状态改变时清空已选择的要素
    this._select.on('change:active', () => {
      this._select.getFeatures().forEach((item) => {
        this._select.getFeatures().remove(item)
      })
    })
  }

  // 操作:绘制
  // Options: 'Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'Circle', 'Square', 'Box'
  draw(type) {
    this.stopDraw() // 停止绘制

    let value = type // 绘制类型
    let geometryFunction = null

    switch (type) {
      case 'Square':
        value = 'Circle'
        geometryFunction = createRegularPolygon(4)
        break
      case 'Box':
        value = 'Circle'
        geometryFunction = createBox()
        break
    }

    this._draw = new Draw({
      source: this._source,
      type: value,
      geometryFunction, // 绘制回调
    })

    this.map.addInteraction(this._draw)
  }

  // 复位:停止绘制
  stopDraw() {
    this.map.removeInteraction(this._draw)
    this._modify.setActive(false)
    this._select.setActive(false)
    this._translate.setActive(false)
  }

  // 操作:修改
  modify(flag = true) {
    this.stopDraw()

    this._select.setActive(flag)
    this._modify.setActive(flag)
  }

  // 操作:拖拽
  translate(flag = true) {
    this.stopDraw()

    this._select.setActive(flag)
    this._translate.setActive(flag)
  }
}

指路

项目地址:cswwww/geojson-editor-ol

系列专栏:
【GeoJSON在线编辑平台】(0)项目启动与前言-CSDN博客

相关推荐
桃园码工31 分钟前
4_使用 HTML5 Canvas API (3) --[HTML5 API 学习之旅]
前端·html5·canvas
桃园码工33 分钟前
9_HTML5 SVG (5) --[HTML5 API 学习之旅]
前端·html5·svg
人才程序员1 小时前
QML z轴(z-order)前后层级
c语言·前端·c++·qt·软件工程·用户界面·界面
m0_548514771 小时前
前端三大主流框架:React、Vue、Angular
前端·vue.js·react.js
m0_748232391 小时前
单页面应用 (SPA):现代 Web 开发的全新视角
前端
孤留光乩2 小时前
从零搭建纯前端飞机大战游戏(附源码)
前端·javascript·游戏·html·css3
伊泽瑞尔.2 小时前
el-tabs标签过多
前端·javascript·vue.js
2401_854391082 小时前
智能挂号系统设计典范:SSM 结合 Vue 在医院的应用实现
前端·javascript·vue.js
觉醒的程序猿2 小时前
vue2设置拖拽选中时间区域
开发语言·前端·javascript
m0_748241123 小时前
前端监控之sourcemap精准定位和还原错误源码
前端·状态模式