Openlayers3事件体系详解

OpenLayers 3 之 事件体系详解 地图上的各种事件触发到底是怎么回事?熟悉前端的肯定知道 javascript 的事件机制,openlayers 既然是 javascript 实现的,那么它就也不例外,也遵循 W3C 的标准,只不过是 openlayers 进行的简化实现。文章首先讲解 openlayers 的事件结构实现,然后结合“切片WMS数据源”(ol.source.TileWMS)对象的事件机制进行实例分析。一. 介绍事件机 阅读详情

地图上的各种事件触发到底是怎么回事?熟悉前端的肯定知道 JavaScript 的事件机制,openlayers 既然是 javascript 实现的,那么它就也不例外,也遵循 W3C 的标准,只不过是 openlayers 进行的简化实现。

文章首先讲解 openlayers 的事件结构实现,然后结合“切片WMS数据源”(ol.source.TileWMS)对象的事件机制进行实例分析。

一. 介绍

事件机制的设计模式是观察者模式(对象间的一对多的依赖关系,当对象的状态发生改变时,依赖它的对象都将得到通知并被自动更新)。对象(也就是包含事件的类)并不创建事件对象实例,它们往往注册某些类型的事件及其监听函数(事件对象作为其第一个参数),在某种类型的事件被分发(dispatch)时,所有监听该类型事件的函数都会触发并执行。所有的事件事件对象实例都有一个 target 属性,对应于触发事件的对象(一般是 dom 元素),监听器的内部 this 默认指向 target,可以通过绑定时候配置。有一些自定义的事件类型,可能有额外的属性。

openlayers 中实现注册和解除监听函数功能的类是 ol.Observable,因此任何继承于 ol.Observable 的类的对象实例都具有注册或者解除注册监听器的能力,并且可以分发事件。

二. openlayers 事件机制结构

Openlayers 的事件类型有地图点击事件、拖拽事件等,但它们都是基于基本的浏览器通用事件,就像 javascript 中使用的一样,OL3 中具体的事件体系结构规定如下图:

事件机制结构

  • event.js,定义了 openlayers 的事件基类,所有事件有关的类都继承这个类;
  • mapevent.js,地图事件的基类,地图的各种事件类型都会继承这个类;
  • mapbrowserevent.js,地图浏览器事件;

  • events

    • event.js,openlayers对于 W3C DOM 2级 Event 接口的精简实现,事件对象中只包含 target type 属性,和 stopPropagationpreventDefault方法;
    • eventtarget.js,openlayers对于 W3C DOM 2级 EventTarget 接口的精简实现,实现中没有捕获模型,没有实现‘事件目标层次结构’,当监听器调用stopProgation 或者 preventDefault时,效果是其他的监听器不会再被调用,和监听器返回 false 一个效果;
    • condition.js,包含了判定满足某种条件的鼠标和键盘事件的函数集合。
  • pointer

    • pointerevent.js,鼠标指针事件的基类;
    • pointereventhandler.js,包含注册、解除注册、触发等一系列与事件有关的工具类;
    • eventsource.js,事件的来源; 
      • mousesource.js,来自鼠标的事件;
      • mssource.js,来自IE 的事件;
      • nativesource.js,来自本地的事件;
      • touchsource.js,触控设备的触摸事件。

以上的解释过于“书面”,其实events 目录中定义的是 W3C 关于浏览器事件规范的精简实现,event.js 定义的就是事件对象,也就是触发事件时返回的事件对象,包含 target 属性,指向绑定的DOM元素;eventtarget.js 定义的是事件目标对象,也就是被注册事件的DOM对象,包含添加和移除特定类型监听函数的能力和分发事件的能力,注册的监听函数维护在 ‘listeners’ 数组中。

三. ol.Observable

ol.Observable提供了从事件目标注册和移除监听器的功能,任何继承于 ol.Observable 的类的对象实例都具有注册或者移除注册监听器的能力。其提供的方法如下:

  • changed(),增加事件对象的版本号(每次事件对象变化,都会增加版本号),并分发 change 事件;
  • dispatchEvent(event),分发事件,并调用所有的监听该类型事件的监听器;
  • getRevision(),获取事件对象的版本号;
  • on(type, listener, opt_this),监听 type 类型的事件,若事件触发,则调用 listener 函数;
  • once(type, listener, opt_this),监听 type 类型的事件(仅一次),若事件触发,则调用 listener 函数,并移除该监听器;
  • un(type, listener, opt_this),移除监听 type 类型的监听函数 listener;
  • unByKey(key),移除对应 key 的监听器,key 一般是由 on() 或者 once() 返回的。

此外还提供了一个静态方法: ol.Observable.unByKey,和原型方法 ol.prototype.unByKey(key)是一致的定义。推荐使用静态方法,其定义如下:

/** 
* Removes an event listener using the key returned by on() or once(). 
* Note that using the {@link ol.Observable.unByKey} static function is to 
* be preferred. 
* @param {ol.events.Key|Array.<ol.events.Key>} key The key returned by on() or once() (or an array of keys). 
* @function 
* @api stable 
*/ 
ol.Observable.prototype.unByKey = ol.Observable.unByKey;

四. ol.source.TileWMS 使用事件实例

ol.source.TileWMS 中有一个通过更新 wms 的请求参数以达到更新图层内容的方法:updateParams(params),定义如下。

/**
 * Update the user-provided params.
 * @param {Object} params Params.
 * @api stable
 */
ol.source.TileWMS.prototype.updateParams = function(params) {
  ol.object.assign(this.params_, params);
  this.resetCoordKeyPrefix_();
  this.resetParamsKey_();
  this.updateV13_();
  this.changed();
};
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

我们看到方法中除了赋值新的 params 给 this.params_ 之外,还调用了四个函数,这四个函数功能分别如下:

  • this.resetCoordKeyPrefix_(),修改 this.coordKeyPrefix 为使用 ‘#’ 分隔符连接的 this.urls 数组;
  • this.resetParamsKey_(),修改 this.paramsKey_ 为使用 ‘/’ 分隔符连接的 this.params 数组;
  • this.updateV13_(),比较参数中指定的 WMS 协议版本号和 ‘1.3’ 版本号,如果不低于1.3,那么返回 true;
  • this.changed(),这个函数是 ol.Observable 中定义的,它会触发 ol.events.EventType.CHANGE 事件,所有的 source 类型都继承 ol.source.Source,而它继承了 ol.Object,其继承了 ol.Observable,因此所有 source 类型中都可以使用事件机制。

接下来我们来看看 changed 函数的定义:

/**
 * Increases the revision counter and dispatches a 'change' event.
 * @api
 */
ol.Observable.prototype.changed = function() {
  ++this.revision_;
  this.dispatchEvent(ol.events.EventType.CHANGE);
};
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里调用的 dispatchEvent(event) 方法,是定义在 events/eventtarget.js 中的方法,因为 ol.Observable 继承了定义在 events/eventtarget.js 中的 ol.events.EventTarget,dispatchEvent 方法是其原型方法。方法的作用是触发一个事件,并调用所有监听该类型事件的 listeners,event 参数可以是字符串,也可以是一个包含 type 属性的事件对象。定义如下:

/**
 * @param {{type: string,
 *     target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
 *     string} event Event or event type.
 * @return {boolean|undefined} `false` if anyone called preventDefault on the
 *     event object or if any of the listeners returned false.
 */
ol.events.EventTarget.prototype.dispatchEvent = function(event) {
  var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
  var type = evt.type;
  evt.target = this;
  var listeners = this.listeners_[type];
  var propagate;
  if (listeners) {
    if (!(type in this.pendingRemovals_)) {
      this.pendingRemovals_[type] = 0;
    }
    for (var i = 0, ii = listeners.length; i < ii; ++i) {
      if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
        propagate = false;
        break;
      }
    }
    var pendingRemovals = this.pendingRemovals_[type];
    delete this.pendingRemovals_[type];
    while (pendingRemovals--) {
      this.removeEventListener(type, ol.nullFunction);
    }
    return propagate;
  }
};
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

函数首先检查事件目标是否有该类型的监听函数,如果有,就依次调用。

OpenLayers 中的 map 实例中包含的所有图层都会添加到ol.MapProperty.LAYERGROUP 中,而在 map 实例初始化时,对 ol.MapProperty.LAYERGROUP 设置了监听函数:

ol.events.listen ( this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP), this.handleLayerGroupChanged_, this);

handleLayerGroupChanged_定义如下:

/**
 * @private
 */
ol.Map.prototype.handleLayerGroupChanged_ = function() {
  if (this.layerGroupPropertyListenerKeys_) {
    this.layerGroupPropertyListenerKeys_.forEach(ol.events.unlistenByKey);
    this.layerGroupPropertyListenerKeys_ = null;
  }
  var layerGroup = this.getLayerGroup();
  if (layerGroup) {
    this.layerGroupPropertyListenerKeys_ = [
      ol.events.listen(
          layerGroup, ol.ObjectEventType.PROPERTYCHANGE,
          this.handleLayerGroupPropertyChanged_, this),
      ol.events.listen(
          layerGroup, ol.events.EventType.CHANGE,
          this.handleLayerGroupMemberChanged_, this)
    ];
  }
  this.render();
};
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

函数首先删除与地图图层相关的所有监听函数,然后重新监听图层组的成员(图层)和属性的变化事件,最后调用 render()函数,重新绘制地图。

五. 总结

本文首先分析了 openlayers 中的事件结构,然后结合ol.source.TileWMS讲解了具体的事件触发机制。

OpenLayers 3 之 地图交互功能(interaction)详解 地图交互功能和上一篇讲的地图控件有些混淆,它们都控制着用户与地图的交互,区别是地图控件的触发都是一些可见的 HTML 元素触发,如按钮、链接等;而交互功能都是一些设备行为触发,都是不可见的,如鼠标双击、滚轮滑动等,手机设备的手指缩放等。      地图的交互功能包含很多,如地图双击放大,鼠标滚轮缩放,矢量要素点选,地图上绘制图形等等。只要是涉及到与地图的交互,就会涉及到 intercation ... 阅读详情

相关推荐

OpenLayers 3 之 Overlay(覆盖物)详解

Overlay 从名字看,是覆盖图、覆盖物的意思,主要的用途就是在地图之上再覆盖一层,用以显示额外的可见元素,可见元素一般是 HTML 元素,利用 overlay,可以将可见元素放置到地图的任意位置,形成地图上再浮动一层的效果。例如在地图上相应的坐标放置一个标志,标签,利用 overlay 都可以做到,具体来说,点击地图上某位置,在点击位置弹出弹出框就是利用了 overlay。

研究与专注 2万+

Openlayers API-Select点击要素图层

Select是交互事件中的一种,用于选择矢量图层上的几何图形,添加选择交互事件后,点击地图上的几何图形或者将鼠标移动到几何图形上时,将获取到几何图形的相关信息,我们可以将选择的几何图形进行高亮显示。使用起来很简单,首先创建一个Select对象,然后再使用Map的addInteraction方法添加该对象。选择的事件包括Single-click, Click, Hover ,Alt+Click等。可以使用condition属性来指定事件类型。 var select = new ol.interact.

ANNENBERG的博客 2017

OpenLayers 3 之 地图控件(control)详解

每一个地图应用都应该有一些工具方便用户控制地图的行为,比如缩放,全屏,坐标控件等等,在 OpenLayers 中怎么添加这些工具呢?下面我给大家介绍一下 OpenLayers 中包含的控件种类,并介绍其使用方法。对控件的定制化,和对 OpenLayers 增加控件和优化控件等超出了本文范围。

研究与专注 2万+

openlayers3自定义事件

&lt;html&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt; &lt;title&gt;Ol3 popup&lt;/title&gt; &lt;link rel="stylesheet" type="te

傲骨雄风的博客 1601

Openlayers实战:启动、取消事件的监测

在Openlayers的实际项目中,我们会用到各种地图事件,比如click,dblclick,change,loadstart … 监测的时候往往用on(‘事件名称’,回调函数)来操作,但是取消这些事件的监控怎么做呢,请参考源代码。

大剑师兰特的GIS世界 926

Openlayers Map事件基础及重点内容讲解

Openlayers map事件是非常重要的交互,没有这些事件,地图存在的意义仅有2%。这些事件都有哪些呢,如何使用呢,我们实战中都有涉猎,一下为基础介绍和API详解。

大剑师兰特的GIS世界 1321

Vue3+OpenLayers实战:封装高效地图绘制组件(点线面矩形圆)

本文详细介绍了在Vue3项目中封装OpenLayers地图绘制组件的实战方法。通过抽象核心绘制逻辑为可复用的组合式函数,并基于此构建了点、线、面、矩形和圆等独立绘制组件,实现了高效的绘制功能。文章重点阐述了组件化封装的优势、具体实现步骤、样式与事件管理,以及如何集成到业务场景中,旨在帮助开发者提升地图应用开发效率与代码可维护性。

y7z8a9的博客 538

Stata中介效应分析实战:从sgmediation安装到Sobel检验结果解读

本文提供了Stata中进行中介效应分析的完整实战指南,重点介绍了第三方命令sgmediation的安装、配置与使用。通过详细案例演示了如何运用Sobel检验分析变量间的间接效应,并深入解读检验结果,帮助研究者厘清自变量影响因变量的具体路径。文章还探讨了Sobel检验的原理、优缺点及结果报告规范,是进行实证研究的实用参考。

weixin_29197051的博客 630

OpenLayers 3 事件应用

OpenLayers 3 事件应用 常用鼠标事件 地图鼠标左键单击事件 对应的类为ol.Map,事件名为singleclick。 地图鼠标左键双击事件 对应的类为ol.Map,事件名为dblclick。 地图鼠标点击事件 对应的类为ol.Map,事件名为click。 地图鼠标移动事件 对应的类为ol.Map,事件名为pointermove。 地图鼠标拖拽事件 对应的类为ol.Map,事件名为pointerdrag。

大树 2598

Ubuntu 上 1Panel 的安装与高效运维实践

本文详细介绍了在Ubuntu系统上安装和高效运维1Panel面板的完整实践指南。内容涵盖了一键安装、Docker容器可视化部署、计划任务自动化以及网站数据库管理等核心功能,并提供了安全加固、资源监控与数据备份等进阶技巧,旨在帮助用户快速搭建并管理一个强大易用的服务器环境。

weixin_29210759的博客 143

Android:Google三方库之Adjust集成详细步骤

Android为APP添加google adjust功能

学习就是我的个性 4476

OpenLayers3, 航线动画实现

本文基于OpenLayers3,实现航线动画的功能。

我哎GIS博客 1815

龙迅LT9611UXC芯片简介:Dual-Port MIPI DSI/CSI to HDMI2.0 with Audio

龙迅半导体推出的LT9611UXC是一款高性能MIPI转HDMI2.0转换器,支持DSI/CSI接口转换,兼容多种视频格式(RGB/YCbCr),最高支持4K@60Hz输出。该芯片集成音频处理(I2S/SPDIF)、色彩空间转换和3D功能,适用于机顶盒、电视盒子等消费电子及车载设备。提供工业级(-40℃~+85℃)和车规级(AEC-Q100认证)版本,采用QFN64封装。

MB16698594834的博客 1334

vue3-openlayers源码解析:揭秘Vue组件如何封装OpenLayers API

**vue3-openlayers**是一个强大的Vue 3地图组件库,它巧妙地将OpenLayers的强大地图功能封装为直观的Vue组件。对于想要在Vue 3项目中集成专业地图功能的开发者来说,vue3-openlayers提供了完美的解决方案。本文将深入解析这个库的源码设计,揭示其如何将复杂的OpenLayers API转化为简单易用的Vue组件。🚀 ## 🗺️ 为什么需要vue3-op

gitblog_00454的博客 1069

MATLAB新手必看:Stewart平台运动学逆解从入门到实战(附完整代码)

本文详细介绍了如何使用MATLAB实现Stewart平台的运动学逆解,从基础原理到完整代码实现,涵盖并联机器人的数学建模、MATLAB编程和Simulink集成。通过实战案例和可视化分析,帮助新手快速掌握Stewart平台的运动学逆解技术,适用于机器人学和控制理论领域的研究与应用。

dream的博客 551

SAP ABAP SSSLERR_PEER_CERT_UNTRUSTED 证书过期+证书导入+案例详解+注意事项

出于 IT 审计与安全管理,外部系统间通讯发布的 API 主流都是 HTTPS 协议,SAP 支持 SSL 证书。SSL 证书是有效期的,当证书失效时将返回错误 SSSLERR_PEER_CERT_UNTRUSTED ,此时需要导入新效期的证书。这篇文章完整讲解了证书过期处理的全过程。

SAP李斌,本人承诺所有原创文章均不使用任何AI生成技术,请大家放心阅读。 2366

OpenLayers 地图事件探究

注:当前使用的是 ol版本,天地图使用的key请到天地图官网申请,并替换为自己的key地图事件贯穿于WebGIS开发的始终,用于实现地图与用户的交互操作。地图缩放、移动使用MapEvent事件;图层渲染、状态使用事件;要素绘制、选择使用事件。

GIS之路 1266

【教程4>第1章>第12节】通过Verilog读取txt格式数据进行测试并将结果导入到matlab

我们在verilog的testbench中,调用txt文件,将上述正弦样本数据作为测试激励输入到verilog模块中。通过这个方法,可以将一些较为复杂的数据导入到verilog中,进行FPGA数据处理模块的开发。即通过w方式打开一个新的txt文件,然后将verilog的输出保存到XY1.txt文件中。这个部分是txt文件的路径,实际使用时,修改为您自己的路径,或者将txt文件放在和我一样的路径中。这个是数据长度,matlab产生的txt多少长度,这个参数就修改为多少长度。这个txt就是保存这段数据的文件。

FPGA/MATLAB学习教程/源码/项目合作开发 1378

openlayers3在地图上定义feature的鼠标移入移出事件

ol3提供了鼠标在feature上的鼠标移入事件,但是并没有提供移出事件所以移出事件是要自定义的,具体思路如下: 1、绘制一个点、线、面的时候会得到一个feature对象使用这个feauture对象注册mousein监听 obj_feature.on('mousein',function (event) { //=====写自己想做事 }) 2、监听地图上的鼠标移动事件: ma...

Wxq666666的博客 6205

【测开求职】面试题:JAVA 吐血整理

本篇文章包含本次测开工程师秋招过程中遇到的所有JAVA面试题,全文两万字,亲测应对各个大厂的面试毫无压力👉

vector的博客 1211

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

OpenLayers3, 设置地图背景

本文基于OpenLayers3,实现地图加入背景图的功能。以上为基于openlayer3 实现设置地图背景图的简单案例,希望对您有帮助~

我哎GIS博客 1803

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

OpenLayers基础教程——常用的地图事件

1、前言 前一篇博客介绍了事件的注册和取消注册,这篇博客就来介绍一下OpenLayers中常用的一些地图事件。 2、地图点击事件 地图点击事件如下所示: click——地图点击事件 singleclick——地图单击事件 dblclick——地图双击事件 测试代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>OpenLayers</tit

HerryDong的博客 6611

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

OpenLayers3, 箭头线绘制实现

本文基于OpenLayers3,实现绘制箭头线的功能。以上为基于openlayer3 实现箭头线绘制功能的简单案例,希望对您有帮助~

我哎GIS博客 1483

3.5.2 可选组件—— OpenLayers 的事件机制

3.5.2         可选组件——OpenLayers的事件机制在OpenLayers框架中,OpenLayers.Events是唯一与组件事件处理相关的类。无论是声明、注册还是触发事件,都是直接在OpenLayers.Events对象上。所以,如果要想让一个对象具有事件处理的能力,需

sasyomaru的专栏 3677

OpenLayers 图层(Layers) 详解

如果不是专业的地图工作者,看到地图,可能觉得地图就是一张将三维世界映射到二维空间,很多信息混杂在一起表示空间信息的动态可交互图片,其实这只是表面现象。实际上地图是由一个或多个图层组成的,使用不同的图层存储不同类型的地物,比如由存储道路的图层,有展示拥堵情况的图层,通常还有一个含有基础地理信息(比如政区划分)的底图图层。

研究与专注 8万+

关于Openlayers Overlay事件监听的一个坑

一、问题产生: 我使用Overlay创建标绘操作的小方块元素,如下代码和如图。 然后我监听小方块的mousedown事件。用原始的事件监听: element.addEventListener('mousedown',process_mousedown); 然后监听map的pointermove事件 this.map.on('pointermove',process_pointmove) 内......

追逐丶的博客 7589
上一篇: javascript入门需要注意的地方
下一篇: openlayers3入门——类、方法、属性详解1
msnaruto
博客等级 码龄12年 2粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值