加入右键菜单,首先我们要监听鼠标右键点击的操作,我们知道鼠标右键事件名是 contextmenu。当鼠标在 html 元素之上,点击鼠标右键,便会触发 contextmenu 事件,在 contextmenu 事件的回调函数中实现对应的显示菜单功能就可以。

那么在 openlayers 中。在地图中加入这个事件,我们从哪里下手呢?首先我们得了解 openlayers 的初始化页面的过程。

openlayers 初始化页面过程

openlayers 也是一个前端库,那么它肯定离不开 html 的运用,比方,我们首先须要在页面放置一个显示地图的 html 元素,一个 div 元素(如果其 id 属性设置为 “map”。后面简称为 map div),然后在地图初始化的时候指定这个元素,openlayers 会首先在这个元素中创建一个 class 为 ol-viewport 的 div 元素,其尺寸保持与 map div 同样,然后在 ol-viewport div 中创建一个 canvas 元素。在这个 canvas 元素中渲染请求到的地图。其次。还会加入一个 class 为 ol-overlaycontainer 的 div 元素,用来放置 overlay。最后,加入一个 class 为 ol-overlaycontainer-stopevent 的 div 元素,主要是放置 openlayers 的控件,上一篇加入 自己定义扩展控件 的文章开篇有讲过。这里不是重点。我们不详细介绍了。

最后形成的 html dom 结构例如以下图:



图1 形成的DOM结构

我们会想到在这个 map div 元素加入事件。然后右键弹出菜单。这个想法非常自然,也确实能够实现,然而我们要想到后面的事情。至少对事情有一个全局的认识再下手,我们显示出菜单后。往往是要依据对应的地图所在位置进行一定的操作,那么我们的 contextmenu 的事件对象包括发生点击的屏幕坐标,可是怎样依据屏幕坐标获得地图中的对应坐标系下的坐标将会比較困难。

困难在哪里呢?主要有以下的三点:

  • 首先,事件对象所含的坐标是相对于整个浏览器的视口、页面或者整个屏幕的。
  • 其次。而显示地图的元素往往又是任意的大小和位置。
  • 最后,屏幕的坐标系和地图的坐标系又往往全然不同,怎样将相对与地图元素的坐标再转化为地图坐标系下的坐标?

首先。我们须要获得事件坐标相对于 map div (包括地图的元素)的坐标,然后将相对于 map div 的坐标转化为地图中的实际坐标。

第一步中,我们能够通过计算获得,可是第二步必须通过 openlayers 来完毕,由于仅仅有 openlayers 对地图的坐标系最清楚。这在 openlayers 中也有相关的功能。庆幸的是。openlayers 中我们能够一步完毕上述操作。仅仅须要一个函数:map.getEventCoordinate(event),在以下的详细实现中,我会详细说到这个函数。

以下我们看看详细怎样实现吧。

鼠标右键菜单详细实现


  • 为了方便,文章中的代码使用了 JQuery。
  • 文章中的实例完整代码能够到我的 GitHub 中查看或者下载。实用的话别忘了点一下 star。


以下我们一步一步地加入右键菜单功能,我们分为三步:

  1. 对 html 元素加入 contextmenu 事件;
  2. 获取地图对应的点击坐标;
  3. 地图对应位置加入菜单 。

对 html 元素加入 contextmenu 事件

html 元素的鼠标右键事件名为 contextmenu,这个事件全部主流浏览器都支持,这里不要混淆 html 新增的属性 contextmenu,这个属性眼下仅仅有 firefox 支持。我们仅仅是使用 oncontextmenu 这个事件。

对包括地图的不论什么 html 元素绑定这个事件都能够,openlayers 会处理坐标转换这些问题。例如以下,map.getViewport() 会返回 openlayers 初始化页面时创建的 class 为 ol-viewport 的 div 元素。也就是直接包括地图的元素。由于浏览器都有默认的右键菜单。所以我们要取消默认的菜单,仅仅要调用 e.preventDefault(); 就可以:

$(map.getViewport()).on("contextmenu", function(event){
e.preventDefault();
// 书写事件触发后的函数
});

获取地图对应的点击坐标

获取地图对应的点击坐标仅仅须要一句就可以。例如以下。

var coordinate = map.getEventCoordinate(event);

函数參数是 oncontextmenu 对应的事件对象。该函数包括对 map.getCoordinateFromPixel() 的调用。map.getCoordinateFromPixel() 參数为 ol.pixel,是一个坐标。数组格式[x, y],事实上现中又调用了 ol.vec.Mat4.multVec2(),该函数完毕处理坐标转换的实际工作。

地图对应位置加入菜单

这里我们结合 overlay 加入菜单,之前的文章介绍过 overlay。这里就不再详细展开了。

首先,我们在 html 页面加入一个文件夹,详细的 css 样式能够自己设定,想看完整源代码的能够到我的 GitHub 中查看或者下载完整的代码:

<div id="contextmenu_container" class="contextmenu">
<ul>
<li><a href="#">设置中心</a></li>
<li><a href="#">加入地标</a></li>
<li><a href="#">距离丈量</a></li>
</ul>
</div>

使用这个 html 元素初始化一个 overlay,并将 overlay 加入到地图中:

var menu_overlay = new ol.Overlay({
element: document.getElementById("contextmenu_container"),
positioning: 'center-center'
});
menu_overlay.setMap(map);

接下来,我们就能够在鼠标右键菜单的事件回调函数中,依据获取的地图坐标位置,设置 overlay 的显示位置:

menu_overlay.setPosition(coordinate);

菜单隐藏

当我们鼠标点击右键,菜单出现,可是我们不能让菜单总是显示在地图中,这时我们能够加入鼠标左键单击,菜单消失功能。或者当选择某项功能时。菜单消失。这个比較easy实现,仅仅要一句便能够实现,放在鼠标左键事件的回调函数或者菜单功能运行函数中就可以。例如以下:

menu_overlay.setPosition(undefined);

总结

这篇文章中,主要讲了 openlayers 初始化页面地图元素的过程,并介绍了在地图上实现“鼠标右键菜单功能”。和隐藏菜单的实现。我们并没有对菜单中的条目绑定事件,由于我们的重点在于实现右键菜单,对于菜单的条目要绑定什么功能,和普通的 javascript 事件绑定并无二致,所以没有展开。

好的,就写到这里,有什么问题,能够在文章以下留言或者给我发邮件。


文章中的实例完整代码能够到我的 GitHub 中查看或者下载,实用的话别忘了点一下 star。


OpenLayers 3 之 加入地图鼠标右键菜单的更多相关文章

  1. jQuery自定义Web页面鼠标右键菜单

    jQuery自定义Web页面鼠标右键菜单 右键菜单是固定的,很多时候,我们需要自定义web页面自定义菜单,指定相应的功能. 自定义的原理是:jQuery封装了鼠标右键的点击事件(“contextmen ...

  2. Qt creator 创建鼠标右键菜单 (不新建类)

    界面 步骤 打开你的界面文件并选中你要添加右键的控件,选择“CustomContextMenu” 右键选择“转到槽...” -> customContextMenuRequested 插入下面代 ...

  3. 如何在C#添加鼠标右键菜单

    C#添加鼠标右键方法步骤: 1 选中要添加右键功能的Form或者控件,打开控件的设计页面. 2 从工具箱中找到ContextMenuStrip控件,将这个控件拖曳到Form或者控件的设计页面上.这时系 ...

  4. 将EmEditor加入到鼠标右键菜单

    在清理系统的时候,无意中将EmEditor的鼠标右键功能给清理掉了,在EmEditor的配置中又没有找到如何加入到鼠标右键菜单的方法,只好使用导入注册表功能了,以下的代码,拷贝到记事本中,保存为EmE ...

  5. JAVA GUI学习 - JPopupMenu鼠标右键菜单组件学习

    public class JPopmenuKnow { public void test() { //为表格添加鼠标右键菜单 JMenuItem jMenuItemFileInfo = new JMe ...

  6. WinForm -- 为TextBox文本框添加鼠标右键菜单

    WinForm -- 为TextBox文本框添加鼠标右键菜单 1. 新建一个WinForm项目,放置一个TextBox控件 2. 从工具箱拖进来一个ContextMenuStrip 3. 将TextB ...

  7. Qt532.【转】Qt创建鼠标右键菜单

    ZC:可以通过 设置  (QWebView*)->setContextMenuPolicy(NoContextMenu); 来关闭 QWebView的默认右键菜单 Qt创建鼠标右键菜单_疯华正茂 ...

  8. Jquery如何禁止鼠标右键菜单

    jquery中使用contextmenu事件,如果返回true,则允许右键菜单:如果返回false,则禁止右键菜单 导入文件 <script type="text/javascript ...

  9. 将Sublime Text 添加到鼠标右键菜单的教程方法

    安装notepad++软件,在菜单右键自动会添加“edit with notepad++"的选项,那么怎么将Sublime Text 添加到鼠标右键菜单呢?下面是我的操作过程,希望有帮助! ...

随机推荐

  1. [Oracle] Transporting Tablespace

    Transporting Tablespace Between Database [测试目的] 利用Oracle TTS(transport tablespace)特性实现表空间合并 [主要步骤] 确 ...

  2. 获取URL中的文件的扩展名

    问题: 尽可能多地写出获取文件扩展名的方法: //方法一(分割数组) function getExt($url){ $arr = explode('.',$url); $len = count($ar ...

  3. Spring整合Disruptor3

    一.什么是Disruptor 从功能上来看,Disruptor 是实现了“队列”的功能,而且是一个有界队列.那么它的应用场景自然就是“生产者-消费者”模型的应用场合了. 可以拿 JDK 的 Block ...

  4. 【原创】Talend ETL Job日志框架——基于P&G项目的一些思考和优化

    一.背景 接触talend也挺长一段时间了,在P&G项目中每天都是使用它开发job,做ETL,也看了前辈开发的很多ETL Job,学到不少.也接触了TAC(talend administrat ...

  5. J.U.C并发框架源码阅读(十五)CopyOnWriteArrayList

    基于版本jdk1.7.0_80 java.util.concurrent.CopyOnWriteArrayList 代码如下 /* * Copyright (c) 2003, 2011, Oracle ...

  6. SpringMVC + Hibernate + MySQL 的简易网页搭建(Dao层 实现篇)

    首先在搭建一个网站后台前,需要明确出一个合理的网页搭建的结构框架,即从DB  ==>  Dao层 ==>Service层 ==>Control层 ==>View层(该层严格意义 ...

  7. 基于django rest framework的mock server实践

    网上找了一下mock server的实现,发现python的基本都是基于flask来实现的,因最近在学django,就尝试用drf实现了下: A brief introduction of sui_m ...

  8. Python的并发并行[1] -> 线程[2] -> 锁与信号量

    锁与信号量 目录 添加线程锁 锁的本质 互斥锁与可重入锁 死锁的产生 锁的上下文管理 信号量与有界信号量 1 添加线程锁 由于多线程对资源的抢占顺序不同,可能会产生冲突,通过添加线程锁来对共有资源进行 ...

  9. the-swift-programming-language 学习笔记

    常量和变量 常量是定义是不可以修改的,在类中定义的常量,可以在构造函数中赋值.let修饰变量是可以修改的.var修饰字符串中字符的遍历for code in string {}for codeunit ...

  10. 【bzoj1415】【聪聪和可可】期望dp(记忆化搜索)+最短路

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=57148470 Descrition 首先很明显是 ...