OpenLayers学习笔记中级篇(五、地图事件)

本文深入介绍了OpenLayers 3中的地图事件,包括鼠标点击、移动、拖拽等,通过示例演示了如何监听和响应事件。同时,讲解了如何自定义事件以实现更灵活的控制,强调了事件在功能模块协作中的重要性。

事件让很多业务的东西串联在一起,在前端中起着非常重要的作用,比如鼠标点击,移动事件。但其应用远不仅如此,现实生活中就存在很多大大小小的事件。 在OpenLayers 3中,同样存在非常多的事件,比如鼠标左键单击,双击等等。 同时还有一些用于各个模块之间进行协作使用的事件,比如ol.Mappostrenderpropertychange事件。 通过这些事件,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的参数具有typeevent属性,必须这样构造吗?在回答这个问题之前,需要先看一下API文档,发现参数类型为goog.events.EventLike,说明它其实用的是google的closure库来实现的,通过closure库的源码我们知道,派发的事件如果是一个对象,那么必须包含type属性,用于表示事件类型。其他的属性可以自由定义,比如此处定义了event属性,并设置对应的值,为的是让鼠标事件传递给feature1的监听函数。

dispatchEvent的参数会被原封不动的传递给事件响应函数,对应代码

feature1.on('mousemove', function(event){

function的参数event,可以通过调试窗口看到此处的eventdispatchEvent的参数是一样的。注意事件名称是可以自定义的,只要派发和监听使用的事件名称是一致的就可以。

我们就完成了自定义事件的三件事:定义事件类型,派发事件,监听事件。

使用自定义事件会带来下面几个好处:

 上面这个例子鼠标移到红色圆后变绿色,但是移出圆后,还是绿色,能不能再移出圆的时候再变成红色呢? 试试用自定义事件的方式再改进一下,实现mouseinmouseout两种事件。这个大家可以自己查阅API然后尝试做一下!

  • 灵活控制,对比一下官网例子和这个例子,就能看出一二。
  • 能更好地满足业务需要,适当地进行扩展。
  • 采用更统一的事件处理框架。
  •  

 关于事件的介绍就先到这儿了,下一节我们会学习地图的交互!大家加油!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值