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

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.mfbz.cn/a/169452.html

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

相关文章

企业经营好不好?看看官方评价指标(适电子元、器件制造业)

一家企业经营的到底好不好&#xff1f;有没有评价标准呢&#xff1f;这里我们不妨参考一下国资委对全国各个行业的考核指标&#xff0c;对照一下自己的企业&#xff0c;就比较清楚自身企业的经营水平了。另外&#xff0c;我们也希望使用ODOO-ERP业财一体系统的企业&#xff0c;…

docker swarm集群部署

文章目录 前言一、安装docker1.1 解压1.2 配置docker 存储目录和dns1.3 添加docker.service文件1.4 docker 启动验证 二、docker swarm 集群配置2.1 关闭selinux2.2 设置主机名称并加入/etc/hosts2.3 修改各个服务器名称&#xff08;uname -a 进行验证&#xff09;2.4 初始化sw…

Java-类和类的关系

代码 总结&#xff1a; 【1】面向对象的思维&#xff1a;找参与者&#xff0c;找女孩类&#xff0c;找男孩类 【2】体会了什么叫方法的形参&#xff0c;什么叫方法的实参&#xff1a; 具体传入的内容 实参&#xff1a; 【3】类和类可以产生关系&#xff1a; &#xff08;1…

Django(九、choices参数的使用、多对多表的三种创建方式、Ajax技术)

文章目录 一、choices参数choices参数的用法choices 参数用法总结 二、MVC与MTV模式1.MVC2.MTV 三、多对多的三种创建方式1.全自动创建2.纯手动创建半自动创建 四、Django与Ajax1.什么是Ajax常见的场景Ajax案例 一、choices参数 在没有用到choices参数之前&#xff0c;我们在D…

如何科学的进行Android包体积优化

这篇文章会分享小厂如何做包体积优化相关主题&#xff0c;涉及内容包括&#xff1a;1) Android包体积优化的一种可能是比较标准的推进做法&#xff0c;2) 大致流程的心路历程和思考方式&#xff0c;3) 如何去总结和分享你们进行过的包体积优化项目。本文不仅仅是一篇分享&#…

PCIe协议加持,SD卡9.1规范达到媲美SSD的速度4GB/s

近日&#xff0c;SD协会&#xff08;SDA&#xff09;宣布了最新的SD Express存储卡的进化&#xff0c;将microSD Express存储卡的速度提高了一倍&#xff0c;达到2GB/s&#xff0c;并引入了4个新的SD Express速度等级&#xff0c;以确保新的SD 9.1规范中最低的顺序性能水平。这…

【自动驾驶解决方案】C++取整与保留小数位

一、C基础 1.1double型保留小数为&#xff0c;并以字符输出 #include <iostream> #include <sstream> #include <iomanip> // 包含std::fixedint main() {//浮点数double number 3.1415926;//转换工具类streamstd::stringstream stream;stream << s…

U-boot(三):start.S

本文主要探讨x210的uboot的start.S文件,也是uboot启动的第一阶段。 头文件 config.h config.h x210_sd.h,由mkconfig脚本生成,包含了开发板的配置宏 rootkaxi-virtual-machine:~/qt_x210v3s_160307/uboot/include# cat config.h /* Automatically generate…

LangChain 组件

输入输出模块 该模块负责与LLM做交互&#xff0c;通过该接口向模型输入 Prompt 并提取模型输出信息。主要包括&#xff1a;提示词、语言模型&#xff0c;输出解析器。 数据连接 已训练好的大语言模型&#xff0c;在训练时使用了大量的训练数据&#xff0c;但这些训练数据中可能…

Windows 下 Sublime Text 2.0.2 下载及配置

1 下载地址&#xff1a; https://www.sublimetext.com/2 Sublime Text 2.0.2 (此版本选择了 portable version)&#xff0c;直接解压就可以使用。 https://download.sublimetext.com/Sublime Text 2.0.2.zip 2 配置Python相关环境 (前提 Pyhon 已加入环境变量) 2.1 新建 py …

为什么大家都不用postman而选择 Apifox呢?

丢掉 Postman&#xff0c;Apifox 更香 作为开发者&#xff0c;丢掉 Postman 和 Jmeter吧&#xff0c;这款国产 API 工具更香&#xff0c;更安全&#xff01;一键即可导入 Postman 数据&#xff01; 一、Apifox 是什么&#xff1f; 1、Apifox 定位 Apifox Postman Swagger …

安全项目简介

安全项目 基线检查 密码 复杂度有效期 用户访问和身份验证 禁用administrator禁用guest认证失败锁定 安全防护软件操作系统安全配置 关闭自动播放 文件和目录权限端口限制安全审计… 等保测评 是否举办了安全意识培训是否有应急响应预案有无第一负责人 工作内容 测评准备…

如何判断sql注入流量特征

如何判断sql注入流量特征 以dvwa的sql注入为例 首先构造一个完整的sql注入请求包 GET /dvwa_2.0.1/vulnerabilities/sqli/?id1&SubmitSubmit HTTP/1.1 Host: 10.9.47.41 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.…

Jenkins自动化部署(虚拟机部署)

文章目录 一、持续集成和持续交付二、自动化部署流程三、虚拟机安装四、安装Jenkins环境4.1.安装java环境4.2. 安装Jenkins4.3.Jenkins配置 五、nginx安装和配置5.1. 安装nginx5.2.通过Linux命令创建文件夹和文件&#xff1a;5.3. 配置nginx 六、将代码上传到Git仓库七、Jenkin…

趣学python编程(六、关于蓝桥杯比赛)

蓝桥杯全国软件和信息技术专业人才大赛简称“蓝桥杯”&#xff0c;是由工业和信息化部人才交流中心举办的国内最大的信息技术竞赛。为促进中小学科技创新&#xff0c;提升中小学生逻辑思维&#xff0c;发现和培养面向未来的科技精英人才。 蓝桥杯介绍 蓝桥杯全国软件和信息技术…

【视觉SLAM十四讲学习笔记】第三讲——旋转矩阵

专栏系列文章如下&#xff1a; 【视觉SLAM十四讲学习笔记】第一讲——SLAM介绍 【视觉SLAM十四讲学习笔记】第二讲——初识SLAM 本章将介绍视觉SLAM的基本问题之一&#xff1a;如何描述刚体在三维空间中的运动&#xff1f; 旋转矩阵 点、向量和坐标系 三维空间由3个轴组成&…

C++数据结构:并查集

目录 一. 并查集的概念 二. 并查集的模拟实现 2.1 并查集类的声明 2.2 并查集的实现 三. 路径压缩 四. 总结 一. 并查集的概念 在生活中&#xff0c;我们经常需要对某一些事物进行归类处理&#xff0c;即&#xff1a;将N个不同的元素划分为几个互不相交的集合。在初始状态…

如何解决网站被攻击的问题:企业网络攻防的关键路径

在当今数字化时代&#xff0c;企业面临着不断升级的网络威胁&#xff0c;网站遭受攻击的风险也与日俱增。解决网站被攻击的问题对企业发展至关重要&#xff0c;不仅关系到企业的信息安全&#xff0c;也直接影响到企业的声誉和利益。从企业发展的角度出发&#xff0c;我们将探讨…

安装oracle19c卡在安装界面

我在个人window10电脑上安装 Oracle 19c 时遇到问题。解压后的数据库文件放在没有中文的文件目录下面&#xff0c;用管理员用户启动 CMD 窗口进行安装&#xff0c;但随后卡在菜单上。 取消安装之后去任务管理器中的服务里停掉OracleRemExecServiceV2服务。 用管理员运行CMD…

在VSCode创建vue项目,出现“因为在此系统上禁止运行脚本”问题

问题&#xff1a;vue : 无法加载文件 C:\Users\***\***\Roaming\npm\vue.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 ht tps:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 解决&#xff…