Openlayer【二】—— 绘制不同的点、线以及给其添加监听事件

news2024/9/20 20:32:31

Openlayer【二】—— 绘制不同的点、线以及给其添加监听事件

接上篇:OpenLayer初始化

在openlayer当中,图层Layer与地图源Source是一对一的关系。当创建了一个图层Layer,相应的需要给图层添加地图源Source,然后将图层Layer添加到地图Map上,就可以得到我们想要的地图了

在Source当中主要包含以下三种Tile、Image、Vector

  • ol.source.Tile对应的是瓦片数据源,现在网页地图服务中,绝大多数都是使用的瓦片地图,而OpenLayers 作为一个WebGIS引擎,理所当然应该支持瓦片。
  • ol.source.Image对应的是一整张图,而不像瓦片那样很多张图,从而无需切片,也可以加载一些地图,适用于一些小场景地图。
  • ol.source.Vector对应的是矢量地图源,点,线,面等等常用的地图元素(Feature),就囊括到这里面了。

1、绘制点

1.1、绘制单个默认点

所以在这一步,我们首先需要创建一个Layer和Source对象,并且把layer加到地图上,最后再往source对象当中添加对应点对象就完成了点的绘制,这里的点(Point)对象需要添加给到source.Vector的Feature元素当中

import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";

const vectorSource = new VectorSource();
const vectorLayer = new VectorLayer({
  source: vectorSource
});
this.map.addLayer(vectorLayer);

const marker = new Feature({
  geometry: new Point([120, 20])
});
vectorSource.addFeature(marker);

如上代码就添加了一个点到地图上了,在官网可以看到new Point()构造需要传递两个参数,一个是点的位置,一个是对象的布局,其是一个可选参数,默认参数是ol.geom.GeometryLayout.XY,还可以设置为ol.geom.GeometryLayout.XYZ、ol.geom.GeometryLayout.XYM 或 ol.geom.GeometryLayout.XYZM,可以通过以下代码进行调整对象的布局

import { GeometryLayout } from 'ol/geom/Geometry';

var point = new Point([10, 20, 100]);
point.setLayout(GeometryLayout.XYZ);

1.2、绘制颜色填充的点

在Feature对象当中可以给整个对象统一设置样式,通过setStyle(),首先我们给点设置为圆形红色并且半径为6 单位(米)并且给圆的外面加上一个绿色宽度为3的边

marker.setStyle(
  new Style({
    image: new Circle({
      radius: 6,
      fill: new Fill({ color: "red" }),
      stroke: new Stroke({
        color: "green",
        width: 3
      })
    })
  })
);

1.3、绘制多个点

只需要循环创建圆点之后,将圆通过addFeature方法添加进去即可

const vectorSource = new VectorSource();
const vectorLayer = new VectorLayer({
  source: vectorSource
});
this.map.addLayer(vectorLayer);

for (let i = 0; i < 500; i++) {
  const marker = new Feature({
    geometry: new Point(this.getRandomCoordinate())
  });

  marker.setStyle(
    new Style({
      image: new Circle({
        radius: 6,
        fill: new Fill({ color: "red" }),
        stroke: new Stroke({
          color: "green",
          width: 3
        })
      })
    })
  );
  vectorSource.addFeature(marker);
}

/**
* 随机生成经纬度
*/
getRandomCoordinate() {
    const minLon = -180; // 最小经度
    const maxLon = 180; // 最大经度
    const minLat = -90; // 最小纬度
    const maxLat = 90; // 最大纬度

    const lon = Math.random() * (maxLon - minLon) + minLon;
    const lat = Math.random() * (maxLat - minLat) + minLat;

    return [lon, lat];
}

在这里插入图片描述

1.4、绘制图标点

绘制图标点只需要给style加上image的相关图标配置即可绘制图标到地图上,如下,这里的anchor表示图标的锚点(图标的中心位置)、opacity表示透明度、scale表示放大缩小层级,src指向对应的图标文件的位置、color表示图标的颜色(对图标进行着色)

marker.setStyle(
  new Style({
    image: new Icon({
      anchor: [0.5, 1],
      opacity: 1,
      scale: 1,
      src: require("./icon/point.png"),
      color: 'green'
    })
  })
);

其中对Icon的属性可以参考官方文档:OpenLayers v8.2.0 API - 类:图标

1.5、给图标点加上文字

给图标加文字和前面设置图标一样,都是直接给style当中添加属性即可,这里添加的是text属性。这里的fill的color表示文字的填充颜色为白色、font属性可以设置文字大小和字体类型、text表示展示的文字内容、scale是一个数组表示横向(x)和纵向(y)的放大缩小层级、offsetX和offsetY分别表示文本在水平和垂直上的偏移量、最后的storke表示文字的描边

feature.setStyle(
  new Style({
    image: new Icon({
      anchor: [0.5, 1],
      opacity: 1,
      scale: 1,
      src: require("./icon/point.png"),
      color: "green"
    }),
    text: new Text({
      fill: new Fill({
        color: "rgba(255,255,255,0.9)"
      }),
      font: "16px monospace",
      text: "文字",
      scale: [1, 1],
      offsetY: -30,
      stroke: new Stroke({ color: "rgba(0,0,0,0.9)", width: 2 })
    })
  })
);

这里对Text的属性可以参考官方文档:OpenLayers v8.2.0 API - 类:文本

1.6、鼠标移入和鼠标移出点事件监听

1.6.1、实现事件监听

在这里可以在给每一个Feature初始化好了之后通过map的pointermove事件(当鼠标在地图上进行移动时触发事件)用来监听,并且获取当前鼠标移动的位置是否包含了这个Feature对象,之后通过目标的featureTarget(地图监听得到的)和最开始初始化得到的进行对比,如果相同则表示鼠标移入到了当前图标,获取对应的样式scale(放大缩小的层级)设置为2即为放大一倍,不相同表示移出,设置会成原来的样式,

当然同理,这里我简化了样式的设置,如果给图标设置了文字的属性可以通过originalStyle.getText().setScale([2, 2])把字体也给放大一倍,其余的样式也同理如此进行设置即可。这样就给页面添加了一些交互事件使得页面看起来更加活泼一点。

let source = new VectorSource();
for (let i = 0; i < 10; i++) {
  let feature = new Feature({
    id: "ddss",
    geometry: new Point(this.getRandomCoordinate())
  });
  feature.setStyle(
    new Style({
      image: new Icon({
        scale: 1,
        src: require("./icon/point.png")
      })
    })
  );
  this.map.on("pointermove", function(event) {
    const featureTarget = this.forEachFeatureAtPixel(event.pixel, function(feature) {
      return feature;
    });

    if (feature === featureTarget) {
      // 鼠标进入
      const originalStyle = feature.getStyle();
      originalStyle.getImage().setScale(2);
      feature.setStyle(originalStyle);
    } else {
      // 鼠标移出
      const originalStyle = feature.getStyle();
      originalStyle.getImage().setScale(1);
      feature.setStyle(originalStyle);
    }
  });
  source.addFeature(feature);
}
let layer = new VectorLayer({
  opacity: 1
});
layer.setSource(source);
this.map.addLayer(layer);
1.6.2、上述实现存在的问题 —— n次监听

在这里其实乍一看这样子用来实现事件监听没什么问题,每一个点都给加上了监听事件,而且去页面上测试一下当鼠标移入移出图标的大小确实会发生变化。那问题究竟在哪呢?

大数据量的情况:

在上面只初始化了10个点到页面上,当初始化100个点呢?1000个点呢?10000个点呢?在里面是循环加上的监听事件,而这个监听事件是很消耗性能的,10个点100个点看起来还不卡,但是1000个点就明显会有卡顿了,当鼠标移入后要两三秒后才回放大,当10000个点整上去之后整个页面直接卡死了,这个时候就需要给这段代码进行优化了,如何优化这个呢?很显然只需要把监听事件挪出来,由10000次监听变成1次监听就好了,后面监听完之后再去判断给哪个图标去放大缩小也就只有n次循环的事了。用循环n次+1次监听来替换掉n次监听性能消耗一下子就被降下去了。

1.6.3、解决方案 —— 一次监听+n次循环

在前面去掉那个事件监听,在把图层Layer添加进去之后,再进行监听,实现如下,在移动的时候进行监听,在监听的时候获取到feature对象也就是单个点对象,之后遍历地图层级上所有的点进行相等匹配,如果满足条件则修改其大小、文字,反之还原成原始样式。

this.map.addLayer(layer);

this.map.on("pointermove", event => {
  const featureTarget = this.map.forEachFeatureAtPixel(event.pixel, feature => {
    return feature;
  });

  source.getFeatures().forEach(feature => {
    const originalStyle = feature.getStyle();
    if (feature === featureTarget) {
      originalStyle.getImage().setScale(2);
      originalStyle.getText().setScale([1, 1]);
      featureTarget.setStyle(originalStyle);
    } else {
      console.log("鼠标移出");
      originalStyle.getImage().setScale(1);
      originalStyle.getText().setScale([0, 0]);
      feature.setStyle(originalStyle);
    }
  });
});

在这里插入图片描述

2、绘制线

2.1、绘制单个默认线

绘制线和绘制点是一样一样的,就是将点对象换成线对象即可。这里的LineString就是线对象。实例化线对象和点对象也是一样,入参分别是一个坐标和一个布局。之后就是创建一个Source把线的Feature添加进去,再创建一个Layer添加到Source里面,最后将Layer线图层添加给到Map即可。这个的LineString对象的坐标可以添加多个,表示多个点连成的线。

let featureLine = new Feature({
  geometry: new LineString([
    [120,20],
    [130,22],
    [135,26]
  ])
});
let source = new VectorSource();
source.addFeature(featureLine);
let layer = new VectorLayer({ opacity: 1 });
layer.setSource(source);
this.map.addLayer(layer);

2.2、添加样式线

和前面给点添加样式一样,这里只需要给线加上Style也就是给线加上了样式,这里还可以直接把style加给Layer图层,那么这个图层下所有的线都会应用这个样式。

const vectorLayer = new VectorLayer({
  source: new VectorSource(),
  style: new Style({
    stroke: new Stroke({
      color: "red",
      width: 2
    })
  })
});

这里的stroke对象可以参考官网:OpenLayers v8.2.0 API - 类:Stroke

2.3、给线添加文字

同2.2一样把text属性添加到Style当中去,但是这里设置的样式是layer的,所以字是在图层上的,如果你需要吧字添加到线上面去,就需要在得到线的Feature对象featureLine,给他重新设置样式

text: new Text({
	// 这里就省略了,和给点加的text属性一致
});

lineFeature.setStyle(
  new Style({
    stroke: new Stroke({...省略}),
    text: new Text({
      fill: new Fill({...省略})
  })
);

在这里插入图片描述

2.4、选中线

在进行选中线的操作和上面选中点是一样的,可以直接沿用前面的方法进行操作。但是这里还可以通过Select对象用来判断线是否被选中的事件

import { Select } from 'ol/interaction'
import { pointerMove } from 'ol/events/condition';

const interaction = new Select({
  condition: pointerMove, // 设置条件为鼠标移动
  layers: [vectorLayer], // 设置监听的图层
  style: function() {
    const style = lineFeature.getStyle();

    // 修改线的样式
    const stroke = style.getStroke();
    stroke.setWidth(5);

    // 修改文字样式
    const text = style.getText();
    text.setScale([1, 1]);

    // 返回新的样式
    return new Style({
      stroke,
      text
    });
  }
});

// 将交互对象添加到地图上
this.map.addInteraction(interaction);

这里的Select对象用于选择矢量特征的交互。默认情况下,所选功能包括 样式不同,因此这种交互可用于视觉突出显示, 以及为其他操作选择功能。同样的在这里对于上面鼠标移入点事件也可以通过该方法进行实现,这里就不做说明了。

属性说明
condition设置监听事件,默认是singleClick单击事件,还可以设置以下事件
pointerMove:鼠标移动时触发事件。 singleClick:鼠标单击时触发事件。 dblclick:鼠标双击时触发事件。 pointerDown:鼠标按下时触发事件。 pointerUp:鼠标释放时触发事件。 pointerEnter:鼠标进入图层时触发事件。 pointerLeave:鼠标离开图层时触发事件。 pointerDrag:鼠标拖动时触发事件。
layers从中选择要素的图层列表
style所选要素的样式,未设置则使用默认样式

这里的Select对象可以参考官网:OpenLayers v8.2.0 API - 类:Select

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Android】画面卡顿优化列表流畅度六(终篇)

上一篇&#xff1a; 【Android】画面卡顿优化列表流畅度五之下拉刷新上拉加载更多组件RefreshLayout修改 场景回顾&#xff1a; 业务经过一年半左右的运行后&#xff0c;出现了明显的列表卡顿情况&#xff1b;于是开始着手进行列表卡顿优化。目前的情况是&#xff1a; 网络图…

8年资深测试,自动化测试常见问题总结,惊险避坑...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、自动化测试简介…

好的CRM系统有哪些核心能力?

CRM是企业管理的重要工具&#xff0c;可以维护管理客户关系&#xff0c;提高企业的核心竞争力。市场营销、销售、客户服务和技术支持等相关领域都需要用到CRM系统。那么一个好的CRM&#xff0c;最核心的能力有哪些&#xff1f; 1.销售自动化 这里简单介绍下销售自动化的功能&…

非关系型数据库Redis(缓存型数据库)

关系型数据库和非关系型数据库的区别 关系型数据库 是一个结构化的数据库&#xff0c;记录方式是行&#xff08;记录对象属性&#xff09;和列&#xff08;声明对象&#xff09; 表与表之间是有关联的&#xff0c;使用sql语句来对指定的表、库进行增删改查 在创建表的时候&…

尽快调整心态,切莫自讨苦吃

退休多年的老龄人的本“人民体验官”闲得无聊&#xff0c;怕被闲出更多病痛&#xff0c;更怕被闲死&#xff0c;所以天天上网坚持职业新闻人的老习惯——上网读新闻&#xff0c;并以一孔之见置评&#xff0c;旨在抛砖引玉。 11月8日&#xff0c;本“人民体验官 ”在推广人民日…

从矿源到指尖——周大福天然钻石的非凡实力

&#xff08;2023年11月20日&#xff0c;北京&#xff09;在近百年历程中&#xff0c;周大福珠宝集团一直致力珠宝工艺传承与创新设计的孕育&#xff0c;于1929年创立周大福品牌&#xff0c;凭借对中国传统黄金工艺的传承与创新、对中国传统文化的融合与发扬&#xff0c;将黄金…

技术岗位竞业协议规避的坑

​ 前言 技术岗位竞业协议指员工在离开公司后&#xff0c;不能在指定期限内从事与公司业务有竞争关系的工作。 有的公司在入职的时候签订&#xff0c;有的在离职的时候签订&#xff08;更有的公司在工作中途补签&#xff09;&#xff0c;但是要记住&#xff0c;签了就生效了…

kettle创建数据库资源库kettle repository manager

数据库资源库是将作业和转换相关的信息存储在数据库中&#xff0c;执行的时候直接去数据库读取信息&#xff0c;很容易跨平台使用。 创建数据库资源库&#xff0c;如图 1.点击Connect 2.点击Repository Manager 3.点击Other Repository 4.点击Database Repository 在选择Ot…

控制原理 | PID控制的三个参数如何影响控制效果?(附参数整定方法)

目录 0 专栏介绍1 PID控制基本原理2 比例控制的作用3 积分控制的作用4 微分控制的作用5 参数整定方法5.1 经验法5.2 临界比例度法5.3 衰减曲线法 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全局规…

面试题c/c++--语言基础

一 、语言基础 1.1 指针 野指针&#xff1a;指针指向的位置是不可知的 悬空指针&#xff1a;指针最初指向的内存已经被释放了的一种指针 两种指针都指向无效内存空间&#xff0c; 即不安全不可控 。需要在定义指针后且在使用之前完成初始化或者使用 智能指针来避免 智能指针 智…

10个Logo设计资源网站,绝对值得你收藏!

看似简单的标志背后的设计过程一点也不简单。优秀的标志个性鲜明&#xff0c;视觉冲击力强&#xff0c;易于识别和记忆。小标志使品牌的理念和形象一目了然地传达给消费者&#xff0c;使消费者产生良好的品牌联想&#xff0c;从而引导和促进消费。 在设计LOGO时&#xff0c;我…

Linux mmap 的作用是什么?

文章目录 1.简介2.相关函数3.mmap和常规文件操作的区别4.作用参考文献 1.简介 mmap&#xff08;memory map&#xff09;即内存映射&#xff0c;用于将一个文件或其它对象映射到进程的地址空间。 2.相关函数 创建映射函数&#xff1a; #include <sys/mman.h>void *mm…

跨境出海人必备的营销指南:海外各大社交媒体的对比

随着全球数字化的加速&#xff0c;社交媒体已经成为人们交流、分享、获取信息的主要渠道。根据最新的全球数字报告 “DIGITAL 2022: GLOBAL OVERVIEW REPORT”显示&#xff0c;截至2022年&#xff0c;全球有46.2亿社交媒体用户&#xff0c;这个数字相当于世界总人口的58.4%。这…

《YOLOv8-seg改进》专栏指导书册 手把手创新教程

&#x1f680;&#x1f680;&#x1f680;YOLOv8-seg创新专栏&#xff1a;https://blog.csdn.net/cv_20231007/category_12490532.html?spm1001.2014.3001.5482 学姐带你学习YOLOv8&#xff0c;从入门到创新&#xff0c;轻轻松松搞定科研&#xff1b; 1&#xff09;手把手教你…

【EI会议征稿】2024年电气技术与自动化工程国际学术会议 (ETAE 2024)

2024年电气技术与自动化工程国际学术会议 (ETAE 2024) 2024 International Conference on Electrical Technology and Automation Engineering 2024年电气技术与自动化工程国际学术会议 (ETAE 2024) 将于2024年3月8-10日在中国杭州召开。电气工程及其自动化和人们的日常生活…

打破传统束缚,释放服务潜能:本地生活服务商聚合系统引领行业新风向!

本地生活服务商聚合系统是一种集合多平台、多项目的创新型服务系统&#xff0c;它打破了传统服务商系统的一对一限制&#xff0c;为创业者和运营商带来了诸多优势。小多将深入探讨本地生活服务商聚合系统的优势。 随着互联网的快速发展&#xff0c;本地生活服务也迎来了蓬勃的发…

Windows RS485\USB转换接头,连接modbus温度传感器接线方法

文章目录 背景接线方式安装RS485\USB转换接头的驱动程序查看COM口号&#xff08;Communication Port&#xff08;通讯端口&#xff09;&#xff09;测试modbus数据传输 背景 买了个rs485 modbus协议的温度传感器&#xff0c;因为想接到windows上&#xff0c;用传感器厂家提供的…

浅谈无线测温产品在菲律宾某工厂配电项目的应用

摘要&#xff1a;配电系统是由多种配电设备和配电设施所组成的变换电压和直接向终端用户分配电能的一个电力网络系统。由于配电系统作为电力系统的一个环节直接面向终端用户&#xff0c;它的完善与否直接关系着广大用户的用电可靠性和用电质量&#xff0c;因而在电力系统中具有…

元宇宙外科手术vrar仿真实验室平台提高了培训效率和安全性

在科研与教育的领域中&#xff0c;实验室的作用举足轻重。然而&#xff0c;传统实验室受限于时间、空间、资源等因素&#xff0c;难以满足日益增长的科研与教育需求。在这一背景下&#xff0c;3D元宇宙仿真实验室应运而生&#xff0c;以其独特的优势&#xff0c;成为科研与教育…

无菌药品生产(A级区域)--气流流型测试可视化烟雾试验详细介绍

技术背景 无菌药品是指法定药品标准中列有无菌检测项目的制剂和原料药&#xff0c;包括注射剂、眼用制剂、无菌软膏剂、无菌混悬剂等。目前工程中&#xff0c;以注射剂产品为主的厂房占据了很大的比重。 无菌药品生产质量风险管理中&#xff0c;人员及其活动被视为重大的污染…