事件让很多业务的东西串联在一起,在前端中起着非常重要的作用,比如鼠标点击,移动事件。但其应用远不仅如此,现实生活中就存在很多大大小小的事件。 在OpenLayers 3中,同样存在非常多的事件,比如鼠标左键单击,双击等等。 同时还有一些用于各个模块之间进行协作使用的事件,比如ol.Map的postrender和propertychange事件。 通过这些事件,OpenLayers 3的功能模块协作一致,同样地,也可以让我们自己二次开发的功能模块运作起来。 同时,根据需要,我们还可以在系统中新增自定义事件,使得我们的开发使用方式同OpenLayers 3更加的一致。在本章节将详细介绍OpenLayers 3中的各种事件,及相关应用。
首先我们先来一个简单的demo:
1、用鼠标点击下面这个地图,将弹出一个对话框,显示点击位置的经纬度:
<!doctype html>
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<meta content=always name=referrer>
<title>点击显示经纬度</title>
<link href="css/ol.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/ol.js" charset="utf-8"></script>
</head>
<body>
<div id="map" style="width: 100%"></div>
<script type="text/javascript">
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
//这儿要注意坐标系的转换
center: ol.proj.transform(
[116.403598,39.917553], 'EPSG:4326', 'EPSG:3857'),
zoom: 10
})
});
// 监听singleclick事件
map.on('singleclick', function(e){
// 通过getEventCoordinate方法获取地理位置,再转换为wgs84坐标,并弹出对话框显示
alert(ol.proj.transform(map.getEventCoordinate(e.originalEvent), 'EPSG:3857', 'EPSG:4326'));
})
</script>
</body>
</html>
运行一下看一下效果:

我们在点击地图的时候会弹出我们当前点击位置的经纬度!代码很简单,但需要注意的是,任意的事件应用,必然会有三个步骤:
- 找准事件发送者,比如上面这个例子,
map就是事件发送者。 如何找到它呢? 一般都是要交互的对象。 - 找准事件名称,比如上面例子中的
singleclick,切忌不要随便想象,或者按照惯例来写名称,初次使用,请一定参照API文档,不然后果自负。 - 编写事件响应函数,在OpenLayers中,事件发送者都会有一个名字为
on的函数,调用这个函数,就能监听指定的事件,响应函数listener具有一个参数event,这个event类就对应于API文档中事件名称后边括号里的类。
这三个步骤缺一不可,如果使用过jquery监听事件,应该对此比较熟悉。 除此之外,关于OpenLayers 3中的事件应用,还有下面两点需要说明:
- 几乎OpenLayers 3中所有的类,都能监听事件和触发事件,因为它们都继承于类
ol.Observable,这个类甚至是ol.Object的父类。 如此可见,OpenLayers在整个引擎中,是多么的依赖于事件通信。 - 而OpenLayers 3的整个事件机制,又是基于Google的
Closure Library。所以如果你对这个库熟悉,那么对OpenLayers 3提供的事件机制会比较熟悉。
2、注销事件,上一节我们做了一个点击地图弹出经纬度的功能, 但如果之后又不需要再响应该事件了,要怎么办。 比如有一个引导用户使用的需求,用户第一次点击地图的时候,需要弹出一个使用说明,之后点击地图就不用再弹出这个使用说明了。 那我们有哪些方式可以做到这一点呢?那么在我们不需要这个功能的时候如何注销它呢?现在我们来做这个demo:
<!doctype html>
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<meta content=always name=referrer>
<title>注销地图点击事件</title>
<link href="css/ol.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/ol.js" charset="utf-8"></script>
</head>
<body>
<div id="map" style="width: 100%"></div>
<script type="text/javascript">
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: ol.proj.transform(
[116.403598,39.917553], 'EPSG:4326', 'EPSG:3857'),
zoom: 10
})
});
// 创建事件监听器
var singleclickListener = function(event){
alert('大家好,这是一个演示如何取消事件监听的应用,之后再点击地图时,你将不会再看到这个说明。');
// 在响应一次后,注销掉该监听器
map.un('singleclick', singleclickListener);
};
map.on('singleclick', singleclickListener);
</script>
</body>
</html>
大家可以自己运行一下看一下效果!大家可以看到在点击完弹窗后再点击地图时就没有监听事件了!
3、我们现在再来写一下常用的监听事件:
我们常用的监听事件包括如下几个方面:
地图鼠标左键单击事件
对应的类为ol.Map,事件名为singleclick。
地图鼠标左键双击事件
对应的类为ol.Map,事件名为dblclick。
地图鼠标点击事件
对应的类为ol.Map,事件名为click。
地图鼠标移动事件
对应的类为ol.Map,事件名为pointermove。
地图鼠标拖拽事件
对应的类为ol.Map,事件名为pointerdrag。
地图移动事件
对应的类为ol.Map,事件名为moveend。
好了,话不多说,直接上代码:
<!doctype html>
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<meta content=always name=referrer>
<title>各种地图事件的监听</title>
<link href="css/ol.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/ol.js" charset="utf-8"></script>
</head>
<body>
<div id="info" style="background-color: #999;">触发事件提示信息</div>
<div id="map" style="width: 100%"></div>
<script type="text/javascript">
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: ol.proj.transform(
[104, 30], 'EPSG:4326', 'EPSG:3857'),
zoom: 10
})
});
// 响应单击事件
map.on('singleclick', function(event){
document.getElementById('info').innerHTML = '触发了ol.Map的单击事件:singleclick';
});
// 响应双击事件
map.on('dblclick', function(event){
document.getElementById('info').innerHTML = '触发了ol.Map的双击事件:dblclick';
});
// 响应点击事件
map.on('click', function(event){
document.getElementById('info').innerHTML = '触发了ol.Map的点击事件:click';
});
// 响应鼠标移动事件,事件太频繁,故注释掉了,可自行验证该事件
// map.on('pointermove', function(event){
// document.getElementById('info').innerHTML = '触发了ol.Map的鼠标移动事件:pointermove';
// });
// 响应拖拽事件
map.on('pointerdrag', function(event){
document.getElementById('info').innerHTML = '触发了ol.Map的拖拽事件:pointerdrag';
});
// 地图移动事件
map.on('moveend', function(event){
document.getElementById('info').innerHTML = '触发了ol.Map的地图移动事件:moveend';
});
</script>
</body>
</html>
然后看一下效果:

我们在对地图做各种动作时,都可以被监听到然后输出出来!
4、最后我们再自定义一个地图事件并且应用,我们接下来就尝试为ol.Feature添加一个mouseover的事件,通过这个事件,就可以实现在鼠标移到Feature上时,改变它的样式。直接上代码:
<!doctype html>
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<meta content=always name=referrer>
<title>点击显示经纬度</title>
<link href="css/ol.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/ol.js" charset="utf-8"></script>
</head>
<body>
<div id="map" style="width: 100%, height: 400px"></div>
<script>
// 在原点处创建一个feature
var feature1 = new ol.Feature({
geometry: new ol.geom.Point([0, 0])
});
// 并设置为半径为100像素的圆,用红色填充
feature1.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 100,
fill: new ol.style.Fill({
color: 'red'
})
})
}));
// 在坐标[5000000, 5000000]处创建另一个feature
var feature2 = new ol.Feature({
geometry: new ol.geom.Point([5000000, 5000000])
});
// 并设置为半径为100像素的圆,用黄色填充
feature2.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 100,
fill: new ol.style.Fill({
color: 'yellow'
})
})
}));
// 创建地图
var map = new ol.Map({
// 设置地图图层
layers: [
// 创建一个使用Open Street Map地图源的瓦片图层
new ol.layer.Tile({source: new ol.source.OSM()}),
// 把之前创建的feature1和feature2放在另一个层里,Vector可以用来放置features
new ol.layer.Vector({source: new ol.source.Vector({
features: [feature1, feature2]
})})
],
// 设置显示地图的视图
view: new ol.View({
center: [0, 0], // 定义地图显示中心于经度0度,纬度0度处
zoom: 2 // 并且定义地图显示层级为2
}),
// 让id为map的div作为地图的容器
target: 'map'
});
// 为地图注册鼠标移动事件的监听
map.on('pointermove', function(event){
map.forEachFeatureAtPixel(event.pixel, function(feature){
// 为移动到的feature发送自定义的mousemove消息
feature.dispatchEvent({type: 'mousemove', event: event});
});
});
// 为feature1注册自定义事件mousemove的监听
feature1.on('mousemove', function(event){
// 修改feature的样式为半径100像素的园,用黑色填充
this.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 100,
fill: new ol.style.Fill({
color: 'black'
})
})
}));
});
// 为feature1注册自定义事件mousemove的监听
feature2.on('mousemove', function(event){
// 修改feature的样式为半径100像素的园,用黑色填充
this.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 100,
fill: new ol.style.Fill({
color: 'green'
})
})
}));
});
</script>
</body>
</html>
看一下效果:
鼠标移动前:

鼠标移动后:

我们实现了这个功能!关键代码在于这:
// 为地图注册鼠标移动事件的监听
map.on('pointermove', function(event){
map.forEachFeatureAtPixel(event.pixel, function(feature){
// 为移动到的feature发送自定义的mousemove消息
feature.dispatchEvent({type: 'mousemove', event: event});
});
});
dispatchEvent的参数具有type和event属性,必须这样构造吗?在回答这个问题之前,需要先看一下API文档,发现参数类型为goog.events.EventLike,说明它其实用的是google的closure库来实现的,通过closure库的源码我们知道,派发的事件如果是一个对象,那么必须包含type属性,用于表示事件类型。其他的属性可以自由定义,比如此处定义了event属性,并设置对应的值,为的是让鼠标事件传递给feature1的监听函数。
dispatchEvent的参数会被原封不动的传递给事件响应函数,对应代码
feature1.on('mousemove', function(event){
里function的参数event,可以通过调试窗口看到此处的event和dispatchEvent的参数是一样的。注意事件名称是可以自定义的,只要派发和监听使用的事件名称是一致的就可以。
我们就完成了自定义事件的三件事:定义事件类型,派发事件,监听事件。
使用自定义事件会带来下面几个好处:
上面这个例子鼠标移到红色圆后变绿色,但是移出圆后,还是绿色,能不能再移出圆的时候再变成红色呢? 试试用自定义事件的方式再改进一下,实现mousein和mouseout两种事件。这个大家可以自己查阅API然后尝试做一下!
- 灵活控制,对比一下官网例子和这个例子,就能看出一二。
- 能更好地满足业务需要,适当地进行扩展。
- 采用更统一的事件处理框架。
关于事件的介绍就先到这儿了,下一节我们会学习地图的交互!大家加油!
本文深入介绍了OpenLayers 3中的地图事件,包括鼠标点击、移动、拖拽等,通过示例演示了如何监听和响应事件。同时,讲解了如何自定义事件以实现更灵活的控制,强调了事件在功能模块协作中的重要性。
&spm=1001.2101.3001.5002&articleId=91372480&d=1&t=3&u=87e02804e6394aefb7bbce02849d59c3)

被折叠的 条评论
为什么被折叠?



