让OpenLayers的SelectFeature控件支持鼠标右键事件

http://www.cnblogs.com/lei3389/archive/2009/04/21/1440458.html

 

OpenLayers上的一个Feature对象单击出现一个气泡很容易实现,但是右键出现点菜单什么的就不容易了,关键在于SelectFeature控件不支持右键事件,所以我就改之。。
修改的源文件是基于OpenLayers2.7+changeset9116
changeset9116修复了SelectFeature不能选取两个以上图层的bug,具体参见http://trac.openlayers.org/changeset/9116
所以有些源代码和官网上下的OpenLayers2.7有点不一样
代码太多了,显得文章比较长,懒得看的就直接下载修改后的用就行了:

OpenLayers2.7 lei3389修改版下载地址:
http://files.cnblogs.com/lei3389/OpenLayers27_ModedBy_lei3389.rar
使用方法本文最后有个例子的

1.首先修改【OpenLayers\Events.js】
修改OL能够捕获的鼠标事件,添加右键事件“contextmenu”

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->      BROWSER_EVENTS: [
        
" mouseover " " mouseout " ,
        
" mousedown " " mouseup " " mousemove "
        
" click " " dblclick " " rightclick " " dblrightclick " ,
        
" resize " " focus " " blur "
        
// added by lei3389
        , " contextmenu "
        
// added end
    ],

 

现在OL已经可以截获鼠标右键了,只是handler没有去处理,下面我们再继续
2.进入【OpenLayers\Handler\Feature.js】
修改这个handler能够处理的事件表

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->             EVENTMAP: {
            
// added by lei
         ' contextmenu ' : { ' in ' ' click ' ' out ' ' clickout ' },
        
// added end
        
        
' click ' : { ' in ' ' click ' ' out ' ' clickout ' },
        
' mousemove ' : { ' in ' ' over ' ' out ' ' out ' },
        
' dblclick ' : { ' in ' ' dblclick ' ' out ' null },
        
' mousedown ' : { ' in ' null ' out ' null },
        
' mouseup ' : { ' in ' null ' out ' null }
    },

 

这里的in和out可以理解为选中和取消选中
这样,这个handler就能够处理contextmenu事件了,但是谁去处理你的事件呢?只能自己添加了:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->      /* *
    *added by lei3389!!!
     * Method: contextmenu
     * Handle contextmenu.  Call the "contextmenu" callback if contextmenu on a feature,
     *     or the "clickout" callback if rightclick outside any feature.
     * 
     * Parameters:
     * evt - {Event} 
     *
     * Returns:
     * {Boolean}
     
*/
      contextmenu:
function (evt) {
         
return   this .handle(evt)  ?   ! this .stopClick :  true ;
    },

这样就交给handle去处理了
触发选中的本来是左键单击和左键双击,现在我们添加上右击

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->         handle:
        {
        
        
//  var click = (type == "click" || type == "dblclick");
        // moded by lei
        // for right click on feature
         var  click  =  (type  ==   " click "   ||  type  ==   " dblclick " ||  type  ==   " contextmenu " );
        
// moded end
            
        }

 

我们添加右键点击只是利用左键点击触发的事件,所以我们要在触发的事件中添加一个参数,以区分是左键还是右键

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->                  if (previouslyIn  &&  inNew) {
                    
//  out of last feature and in to another
                     this .triggerCallback(type,  ' out ' , [ this .lastFeature]);
                    
                   
//  this.triggerCallback(type, 'in', [this.feature]);
                     // moded by lei3389
                     // for add a param
                     this .triggerCallback(type,  ' in ' , [ this .feature,type]);
                    
// end
                }  else   if ( ! previouslyIn  ||  click) {
                    
//  in feature for the first time
                    //  this.triggerCallback(type, 'in', [this.feature]);
                     // moded by lei3389
                     // for add a param
                     this .triggerCallback(type,  ' in ' , [ this .feature,type]);
                    
// end
                }


3.进入【OpenLayers\Control\SelectFeature.js】
handler只是为control服务的,我们让handler处理了右键事件也是为control处理的
刚刚添加的参数就要有用了:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->      /* *
     * Method: clickFeature
     * Called on click in a feature
     * Only responds if this.hover is false.
     *
     * Parameters:
     * feature - {<OpenLayers.Feature.Vector>} 
     
*/
    
// clickFeature: function(feature) 
     // moded by lei3389
     // for add a param
    clickFeature:  function (feature,triggertype) {
    
// end
         if ( ! this .hover) {
            
var  selected  =  (OpenLayers.Util.indexOf(
                feature.layer.selectedFeatures, feature) 
>   - 1 );
            
if (selected) {
                
if ( this .toggleSelect()) {
                    
this .unselect(feature);
                } 
else   if ( ! this .multipleSelect()) {
                    
this .unselectAll({except: feature});
                }
            } 
else  {
                
if ( ! this .multipleSelect()) {
                    
this .unselectAll({except: feature});
                }
                
// moded by lei3389
                //  this.select(feature);
                 this .select(feature,triggertype);
                
                
// end
            }
        }
    },

 

然后这里也得添加一个参数:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
    
/* *
     * Method: select
     * Add feature to the layer's selectedFeature array, render the feature as
     * selected, and call the onSelect function.
     * 
     * Parameters:
     * feature - {<OpenLayers.Feature.Vector>} 
     
*/
    
// moded by lei3389
     // for add a param ---triggertype
     
   
//  select: function(feature) 
    select:  function (feature,triggertype){
    
// end
         var  cont  =   this .onBeforeSelect.call( this .scope, feature);
        
var  layer  =  feature.layer;
        
if (cont  !==   false ) {
            cont 
=  layer.events.triggerEvent( " beforefeatureselected " , {
                feature: feature
            });
            
if (cont  !==   false ) {
                layer.selectedFeatures.push(feature);
                
this .layerData  =  {};

                
var  selectStyle  =   this .selectStyle  ||   this .renderIntent;
                
                layer.drawFeature(feature, selectStyle);
                layer.events.triggerEvent(
" featureselected " , {feature: feature});
               
            
// moded by lei3389
             // for add another "handler"
              // this.onSelect.call(this.scope, feature);
             switch (triggertype){
                
case   " click " :
                
this .onSelect.call( this .scope, feature);
                
break ;
                
case   " contextmenu " :
                
this .onRightSelect.call( this .scope, feature);
                
break ;
                
default :
                
this .onSelect.call( this .scope, feature);
                }
            
            
// end

            }
        }
    },

 

当然还得添加一个属性,为使用我们刚才修改的成果提供一个调用的接口

Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->        /*************************
        *added by lei3389!!!!
        *APIProperty: onRightSelect
        *{Function} Optional function to be called when a feature is selected by RighClick of mouse .
        *The function should expect to be called with a feature.
        
*/
        onRightSelect: 
function(){},


4.现在对OL库的修改已经over了,我们自己使用的时候就可以用了
到自己的代码中来
首先屏蔽掉默认的右键:
      //forbid the mouse's default rightclick
      map.div.oncontextmenu = function () { return false;}
然后就可以像定义左键一样来定义鼠标右键了:
sample:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->        // add selectStationControl
      selectFeatureControl  =   new  OpenLayers.Control.SelectFeature([VectorLayer1,VectorLayer2,VectorLayer3],
                {onSelect: onFeatureSelect, 
                 onUnselect: onFeatureUnselect,
                                 onRightSelect: onFeatureRightSelect
                });
            map.addControl(selectFeatureControl);
      selectFeatureControl.activate();

 

5.应该这样就对右键的修改就over了吧,我把我自己用的OL上传了.

其中包括了SelectFeature控件对多层选择的支持+右键支持
另外还有和本文不相干的一点修改:
是关于ol解析GML v3.0的posList节点的问题,也可能是esri生成gml的时候esri本身的问题,但是arcgis的源代码我改不了。。只能对OL动手了~~
【OpenLayers.Format.GML】

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->  linestring:  function (node, ring) {
            
/* *
             * Two coordinate variations to consider:
             * 1) <gml:posList dimension="d">x0 y0 z0 x1 y1 z1</gml:posList>
             * 2) <gml:coordinates>x0, y0, z0 x1, y1, z1</gml:coordinates>
             
*/
                    
                
var  dim  =  parseInt(nodeList[ 0 ].getAttribute( " dimension " ));
                  
/* *
                * added by lei3389
                *dim will be 'NAN' for esri didnot give GML V3 the dimension attribute!
                
*/
                
if (dim = ' NAN ' )dim = 2 ;
                
/* *
                * end
                
*/


6.终于完了,好长啊
OpenLayers2.7 lei3389修改版下载地址:
http://files.cnblogs.com/lei3389/OpenLayers27_ModedBy_lei3389.rar

<think>嗯,用户问的是如何在Vue3中处理鼠标右键事件。我需要先回忆一下Vue3的事件处理机制,尤其是针对鼠标右键的部分。首先,记得在Vue中,可以使用@事件名来绑定事件,比如@click或者@contextmenu。不过右键默认会触发浏览器的上下文菜单,所以可能需要阻止默认行为。 根据引用[1]里的内容,提到在Vue中阻止浏览器的默认右键事件,这可能涉及到在事件处理函数中使用event.preventDefault()。另外,引用[2]和[3]都提到了如何处理右键事件,特别是覆盖默认行为。比如,使用@contextmenu.prevent或者直接在方法里调用preventDefault()。 然后,用户可能还关心如何在处理右键事件的同时,阻止其他可能冲突的事件,比如OpenLayers的拖拽,但这个问题可能不在当前范围内。不过需要明确说明如何在Vue3中基础地处理右键事件。 接下来,步骤可能包括:绑定右键事件、阻止默认菜单、自定义处理逻辑。可能需要示例代码,比如在模板中使用@contextmenu.prevent="handleRightClick",然后在方法里定义handleRightClick函数。 另外,引用[3]提到在Electron客户端中可能需要自定义右键菜单,而不仅仅是浏览器环境。所以可能需要区分浏览器和Electron的情况,但用户的问题比较基础,可能只需要覆盖浏览器默认行为即可。 还需要注意Vue3的语法,比如使用setup函数和Composition API,或者Options API。可能需要给出两种方式的示例,或者选择最常见的方式,比如使用<script setup>语法。 总结一下,回答的结构应该是:1. 阻止默认行为,2. 绑定事件,3. 自定义处理。代码示例应该清晰,展示如何阻止默认菜单,并在方法里执行自定义操作,比如显示自定义菜单或者执行复制粘贴功能。 还要检查是否有遗漏,比如事件对象是否需要传递$event,或者是否需要考虑事件冒泡。比如,引用[2]提到使用@mousedown并检查event.button的值,这样可能更灵活,因为contextmenu事件有时可能有兼容性问题,但使用@contextmenu更直接。 最后,确保回答符合用户的要求,即Vue3中的处理方法,所以需要明确使用Vue3的语法,比如Composition API中的setup函数,或者使用<script setup>的语法糖。</think>### 如何在Vue3中处理鼠标右键事件? 在Vue3中处理鼠标右键事件,**核心是阻止浏览器的默认右键菜单并绑定自定义事件**。以下是具体实现方法: --- #### 1. 阻止默认右键事件 浏览器默认右键会触发`contextmenu`事件并显示系统菜单。需通过以下方式阻止默认行为: - **使用`@contextmenu.prevent`修饰符** 在模板中绑定事件时直接添加`.prevent`,例如: ```html <div @contextmenu.prevent="handleRightClick">右键此处</div> ``` - **手动调用`event.preventDefault()`** 若需要更灵活控制(如条件性阻止),可在事件处理函数中操作: ```javascript const handleRightClick = (event) => { event.preventDefault(); // 自定义逻辑 }; ``` --- #### 2. 绑定自定义右键事件 可通过以下两种方式实现: ##### 方式一:使用`@contextmenu`事件 ```html <template> <div @contextmenu.prevent="showCustomMenu($event)"></div> </template> <script setup> const showCustomMenu = (event) => { // 获取鼠标位置 const x = event.clientX; const y = event.clientY; // 显示自定义菜单(需自行实现UI组件) }; </script> ``` ##### 方式二:通过`@mousedown`判断按键 若需兼容复杂场景(如区分左/右键),可监听`mousedown`事件并检查`event.button`: ```html <template> <div @mousedown="handleMouseDown"></div> </template> <script setup> const handleMouseDown = (event) => { if (event.button === 2) { // 右键button值为2 event.preventDefault(); // 执行右键逻辑 } }; </script> ``` --- #### 3. 实现自定义右键菜单 结合UI框架(如Element Plus)或原生HTML实现菜单组件: ```html <template> <div @contextmenu.prevent="openMenu($event)"> <div v-show="isMenuVisible" class="custom-menu" :style="{ left: menuX + 'px', top: menuY + 'px' }"> <button @click="copy">复制</button> <button @click="paste">粘贴</button> </div> </div> </template> <script setup> import { ref } from 'vue'; const isMenuVisible = ref(false); const menuX = ref(0); const menuY = ref(0); const openMenu = (event) => { isMenuVisible.value = true; menuX.value = event.clientX; menuY.value = event.clientY; }; const copy = () => { /* 复制逻辑 */ }; const paste = () => { /* 粘贴逻辑 */ }; </script> ``` --- #### 注意事项 - **Electron客户端场景** 在Electron中需完全覆盖默认行为,并依赖`clipboard`模块实现复制粘贴[^3]。 - **事件冲突处理** 若与其他库(如OpenLayers)结合,需额外阻止其内置事件(如拖拽地图)[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值