vue2+Ts中openLayer绘图工具组件封装

vue2+Ts中openLayer绘图工具组件封装

效果:
在这里插入图片描述
封装组件代码:

<!-- openLayer绘图工具 -->
<template>
  <a-button-group v-show="isShow">
    <a-button v-if="shouldShowButton('point')" @click="draw('Point')">
      绘点
      <a-icon type="dot-chart" />
    </a-button>
    <a-button v-if="shouldShowButton('line')" @click="draw('LineString')">
      绘线
      <a-icon type="line-chart" />
    </a-button>
    <a-button v-if="shouldShowButton('polygon')" @click="draw('Polygon')">
      绘面
      <a-icon type="border" />
    </a-button>
    <a-button v-if="shouldShowButton('edit')" @click="edit()">
      编辑
      <a-icon type="edit" />
    </a-button>
    <a-button v-if="shouldShowButton('undo')" @click="undo()">
      撤销
      <a-icon type="undo" />
    </a-button>
    <a-button v-if="shouldShowButton('redo')" @click="redo()">
      重做
      <a-icon type="redo" />
    </a-button>
    <a-button v-if="shouldShowButton('save')" @click="save()">
      保存
      <a-icon type="save" />
    </a-button>
  </a-button-group>
</template>

<script lang="ts">
import abpbase from '@/libs/abpbase';
import VectorSource from 'ol/source/Vector';
import Map from 'ol/Map';
import { Component, Emit, Prop } from 'vue-property-decorator';
import ol from 'ol';
import VectorLayer from 'ol/layer/Vector';
import Draw, { createRegularPolygon } from 'ol/interaction/Draw';
import Modify from 'ol/interaction/Modify';
import {
 singleClick, doubleClick, pointerMove, never,
} from 'ol/events/condition';
import Select from 'ol/interaction/Select';
import Translate from 'ol/interaction/Translate';
import Snap from 'ol/interaction/Snap';
// eslint-disable-next-line import/no-unresolved
import * as jsts_io from 'jsts/org/locationtech/jts/io';
import {
 Style, Fill, Stroke, Circle,
} from 'ol/style';
import {
  LinearRing,
  LineString,
  MultiLineString,
  MultiPoint,
  MultiPolygon,
  Point,
  Polygon,
} from 'ol/geom.js';
import MapBrowserEventType from 'ol/MapBrowserEventType';

@Component({
  name: 'OpenLayerDrawTool',
  components: {
  },
})
export default class OpenLayerDrawTool extends abpbase {
  /**
   * 最大可绘制要素数量
   */
  @Prop({type:Number, default:1})
  maxFeatures

  @Prop({ type: Array, default: () => ["point", "line", "polygon", "undo", "redo", "save", "edit"] })
  buttonsToShow: string[];

  /**
   * 编辑操作
   */
  editOperation: Modify;

  shouldShowButton(buttonName: string): boolean {
    return this.buttonsToShow.includes(buttonName);
  }

  /**
   * 绘制的矢量图层
   */
  drawVectorLayer: VectorLayer<any>;

  /**
   * 绘制的数据源
   */
  drawSource: VectorSource;

  /**
   * 传入的openLayer地图
   */
  map: Map = null;

  /**
   * 绘制操作
   */
  drawOperation: Draw;

  /**
   * 绘制的图形堆栈
   */
  drawStack = []

  /**
   * 重做的图形堆栈
   */
  redoStack = []

  selectOperation: Select

  translateOperation: Translate

  snapOperation: Snap

  get isShow() {
    return this.map != null;
  }

  /**
   * 初始化地图控件,需要在父组件调用;
   * @param map openLayer地图对象
   * @param requestDataId 请求的数据参数
   */
  initCtrl(map: Map) {
    this.map = map;
    this.drawSource = new VectorSource();

    const createCustomStyle = () => (feature) => {
        const geometryType = feature.getGeometry().getType();
        let style;
        switch (geometryType) {
          case 'Point':
            style = new Style({
              image: new Circle({
                radius: 6,
                fill: new Fill({ color: 'rgba(255, 0, 0, 0.5)' }),
                stroke: new Stroke({ color: 'red', width: 2 }),
              }),
            });
            break;
          case 'LineString':
            style = new Style({
              stroke: new Stroke({
                color: 'blue',
                width: 4,
              }),
            });
            break;
          case 'Polygon':
            style = new Style({
              fill: new Fill({ color: 'rgba(0, 255, 0, 0.2)' }),
              stroke: new Stroke({ color: 'green', width: 3 }),
            });
            break;
          default: {
            break;
          }
        }

        return style;
      };

    this.drawVectorLayer = new VectorLayer<any>({
      source: this.drawSource,
      style: createCustomStyle(),
      zIndex: 999,
    });
    this.map.addLayer(this.drawVectorLayer);
    this.$forceUpdate();
  }

  draw(type) {
    this.map.removeInteraction(this.drawOperation);
    this.drawOperation = new Draw({
      source: this.drawSource,
      type,
      condition: (event) => event.type === MapBrowserEventType.POINTERDOWN && event.originalEvent.button === 0,
    });
    this.map.addInteraction(this.drawOperation);

    this.drawOperation.on('drawend', (e) => {
      // 为要素分配一个唯一的 ID
      e.feature.set('id', Date.now());

      this.drawStack.push(e.feature);
      // 如果绘制的图形数量超过最大限制,移除最早添加的图形
      if (this.drawStack.length > this.maxFeatures) {
        const firstFeature = this.drawStack.shift();
        this.drawSource.removeFeature(firstFeature);
      }
      this.map.removeInteraction(this.drawOperation);
    });
  }

  undo() {
    const lastFeature = this.drawStack.pop();
    if (lastFeature) {
      this.drawSource.removeFeature(lastFeature);
      this.redoStack.push(lastFeature);
    }
  }

  redo() {
    const lastFeature = this.redoStack.pop();
    if (lastFeature) {
      // 如果绘制的图形数量达到最大限制,移除最早添加的图形并将其从重做堆栈中移除
      if (this.drawStack.length >= this.maxFeatures) {
        const firstFeature = this.drawStack.shift();
        this.drawSource.removeFeature(firstFeature);
      }
      this.drawSource.addFeature(lastFeature);
      this.drawStack.push(lastFeature);
    }
  }

  save() {
    const parser = new jsts_io.OL3Parser();
    parser.inject(
        Point,
        LineString,
        LinearRing,
        Polygon,
        MultiPoint,
        MultiLineString,
        MultiPolygon,
    );

    const format = new jsts_io.WKTWriter();
    const features = this.drawSource.getFeatures();
    const wkts = features.map((feature) => {
      const olGeom = feature.getGeometry();
      const jstsGeom = parser.read(olGeom);
      return format.write(jstsGeom);
    });
    console.log(JSON.stringify(wkts));
  }

  mounted() {

  }

  edit() {
    // 移除 drawOperation 交互
    this.map.removeInteraction(this.drawOperation);

    // // 创建 selectOperation 交互对象
    this.selectOperation = new Select({
      condition: singleClick,
    });

    this.map.addInteraction(this.selectOperation);

    // 创建 translateOperation 交互对象
    this.translateOperation = new Translate({
      features: this.selectOperation.getFeatures(),
    });

    this.map.addInteraction(this.translateOperation);

    // 创建 modifyOperation 交互对象
    this.editOperation = new Modify({
      features: this.selectOperation.getFeatures(),
    });
    this.editOperation.setActive(false);

    this.map.addInteraction(this.editOperation);

    this.editOperation.on('modifyend', (e) => {
      // 更新 drawStack 中的要素
      const updatedFeature = e.features.getArray()[0];
      const featureIndex = this.drawStack.findIndex(
          (feature) => feature.get('id') === updatedFeature.get('id'),
      );
      if (featureIndex >= 0) {
        this.drawStack.splice(featureIndex, 1, updatedFeature);
      }
    });

    // 为地图添加双击事件侦听器
    this.map.on('dblclick', (event) => {
      const features = this.map.getFeaturesAtPixel(event.pixel);
      if (features && features.length > 0) {
        this.editOperation.setActive(true);
        this.snapOperation.setActive(true);
        this.translateOperation.setActive(false);
      } else {
        this.editOperation.setActive(false);
        this.snapOperation.setActive(false);
        this.translateOperation.setActive(true);
      }
    });

    // 为地图添加 pointermove 事件侦听器
    // this.map.on('pointermove', (event) => {
    //   const features = this.map.getFeaturesAtPixel(event.pixel);
    //   if (features && features.length > 0) {
    //     this.editOperation.setActive(true);
    //   } else {
    //     this.editOperation.setActive(false);
    //   }
    // });
  }

  // 初始化
  // init() {
  // }

  // created() {
  // }
}
</script>

<style lang="less" scoped>
.home-wrap {
  min-width: 1280px;
  overflow: auto;
}
</style>

父组件使用:

<div class="absolute right-4 top-4">
   <open-layer-draw-tool ref="drawTool"></open-layer-draw-tool>
</div>

initDrawTool() {
     this.$nextTick(() => {
       (this.$refs.drawTool as any).initCtrl(this.map);
     });
  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/627514.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux的 /usr/sbin/nologin /sbin/nologin /bin/false /etc/nologin 的作用与区别

/usr/sbin/nologin /sbin/nologin /bin/false /etc/nologin 的作用与区别 /usr/sbin/nologin /sbin/nologin /bin/false 这三者的作用几乎一样&#xff0c;都是禁止用户登录。 /usr/sbin/nologin /sbin/nologin 是同一个文件&#xff0c;通过软连接指向。 当把用户的bash设置…

Malbers Inventory System

Inventory插件为Malbers动物管理员生态系统带来了强大的库存系统&#xff0c;具有以下功能&#xff1a;通知系统、库存集、自定义物品反应等 ✔️特征 项目管理 收集和存储项目 库存显示 通知系统 物品所有者 库存集合 项目操作 保存和加载&#xff08;基于JSON.Net&#xff0c…

在 CSS 中使用 text-emphasis 来增强文本的趣味性

在CSS中设置文本样式的方法有很多。您可以更改颜色、大小、字体&#xff0c;甚至添加阴影和轮廓等效果。但最近&#xff0c;我了解到一个我以前没有听说过的时尚 CSS 属性&#xff0c;它非常棒&#xff01; 它被称为文本强调&#xff08;text-emphasis&#xff09;&#xff0c…

python数据可视化:层次聚类热图clustermap()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 python数据可视化&#xff1a; 层次聚类热图 clustermap() [太阳]选择题 请问关于以下代码表述错误的选项是&#xff1f; import seaborn as sns import matplotlib.pyplot as plt import n…

低成本窗帘电机解决方案KP81101 3.6A有刷直流电机H桥驱动器代替DRV8871

KP81101是一款有刷直流电机驱动器&#xff0c;适用于家用电器、工业设备和其他有刷直流电机、步进电机应用场合。驱动器由四个 NMOS 构成的 H 桥组成&#xff0c;两个逻辑输入控制全桥驱动器&#xff0c;以驱动直流有刷电机电流双向流动。驱动器的最大峰值电流能力为 3.6A。芯片…

Warning logs 2024-05-15

mysql数据库中文模糊查询时出现异常 Error querying database. Cause: java.sql.SQLException: Illegal mix of collations for operation like Select("select f.* from fundDetails f" " where (case when #{keyword} is not null then f.operateTime like c…

软件项目验收第三方测试报告如何获取

软件项目验收第三方测试报告是确保软件质量、安全性和稳定性的重要环节。对于企业和开发者来说&#xff0c;获取一份全面、专业的第三方测试报告&#xff0c;对于提升软件产品的竞争力和用户满意度至关重要。本文将介绍如何获取软件项目验收第三方测试报告&#xff0c;以及相关…

13.监控redis

1.状态信息 redis-cli keys * info select 0-15#16个库&#xff0c;依次查看即可2.导入模板 在zabbix-server界面-模板-导入-选择文件-redis.xml <?xml version"1.0" encoding"UTF-8"?> <zabbix_export><version>2.0</version&g…

全栈中VUE的install报错说taobao仓库不好使的解决办法

长话短说&#xff0c;就是报错了&#xff0c;直接上干货。 step1&#xff1a;查看设置&#xff0c;主要是看registry npm config getstep2&#xff1a;设置仓库 npm config set registry https://registry.npmmirror.comstep3&#xff1a;再运行步骤一的指令查看仓库是不是变…

Java 循环结构 - for, while 及 do...while

Java 循环结构 - for, while 及 do…while 顺序结构的程序语句只能被执行一次。 如果您想要同样的操作执行多次&#xff0c;就需要使用循环结构。 Java中有三种主要的循环结构&#xff1a; while 循环 do…while 循环 for 循环 在 Java5 中引入了一种主要用于数组的增强型 f…

刷代码随想录有感(66):回溯算法——组合问题的优化(剪枝)

代码&#xff1a;将for循环中i的搜索范围进行缩小&#xff0c;免去多余的不可能符合条件的操作。 for(int i start; i < n-(k-tmp.size())1;i) 实质是剪枝&#xff0c;拿n4,k4作比较&#xff1a; 显然结果只可能是[1,2,3,4]&#xff0c;选取顺序只可能是1-2-3-4&#xff…

Kafka 核心属性速览

目录 1. 背景 2. Kafka的核心属性 2.1. Broker 2.2. Partitions 2.3. Replicas 3. 实践 4. 参考 1. 背景 Kafka是一个流行队列组件&#xff08;在AWS上叫MSK&#xff09;&#xff0c;其他的队列还有rocketMQ、rabbitMQ。就我个人而言&#xff0c;我只是一个使用…

图文详解JUC:Wait与Sleep的区别与细节

目录 一.Wait() 二.Sleep() 三.总结Wait()与Sleep()的区别 一.Wait() 在Java中&#xff0c;wait() 方法是 Object类中的一个方法&#xff0c;用于线程间的协作。当一个线程调用wait() 方法时&#xff0c;它会释放对象的锁并进入等待状态&#xff0c;直到其他线程调用相同对…

Ps 滤镜:素描

Ps菜单&#xff1a;滤镜/滤镜库/素描 Filter/Filter Gallery/Sketch “素描”滤镜组中的滤镜可以将纹理添加到图像上&#xff0c;还适用于创建美术或手绘外观。许多“素描”滤镜在重绘图像时使用前景色和背景色。 半调图案 Halftone Pattern “半调图案”滤镜通过创建一种特定图…

【微信小程序开发(从零到一)【婚礼邀请函】制作】——任务分析和效果实现的前期准备(1)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

【069】基于SpringBoot+Vue实现的企业资产管理系统

系统介绍 基于SpringBootVue实现的企业资产管理系统管理员功能有个人中心&#xff0c;用户管理&#xff0c;资产分类管理&#xff0c;资产信息管理&#xff0c;资产借出管理&#xff0c;资产归还管理&#xff0c;资产维修管理。用户可以对资产进行借出和归还操作。因而具有一定…

详解lighthouse通过命令行方式运行并生成html测试报告的方法

lighthouse可以通过命令行的方式运行并生成html报告&#xff0c;我们可以通过lighthouse --help 命令查看命令行的详细用法&#xff0c;在这里我仅列出最常用的命令行使用方法&#xff01; 常用lighthouse命令行参数详解 * --chrome-flags&#xff1a;传递自定义标志给Chrome…

动态el-form表单以及动态禁用

当右侧下拉框选中为 长期有效,那么左侧输入框为禁用状态; <el-form-item label"证明有效期" class"is-required"><div v-for"(item,index) in form.arrayDat" :key"index" style"width: 100%;display: flex;justify-co…

记录一期Typecho WebShell木马渗透的经历

我创建了一个Typecho的轻量博客,之前一直是本地运行,最近才上了公网,平时自己也是粗心大意,把密码也写在第一篇博文里面 有一天,我突发奇想的想要提交更新,本博客是通过git进行代码版本管理的避免自己修改官方源码出现了问题,无法还原,也定时备份SQL, 然后莫名其妙的发现多了…

html--地图

<!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><title>ECharts</title><!--Step:1 引入一个模块加载器&#xff0c;如esl.js或者require.js--><script src"js/esl.js"></scr…