Javascript Google Map V3 上下文菜单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7168394/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:08:27  来源:igfitidea点击:

Google Map V3 context menu

javascriptgoogle-maps-api-3contextmenu

提问by Horst Walter

I am looking for a Google Map V3 context menu library. I have found some code examples here

我正在寻找 Google Map V3 上下文菜单库。我在这里找到了一些代码示例

  1. Gizzmo's blog
  2. Google API tips
  3. GMap3
  4. How I got ..
  1. Gizzmo 的博客
  2. 谷歌 API 提示
  3. 地图3
  4. 我怎么得到..

Stack overflow question Google maps v3 - Contextual menu available?of April also just came up with the above examples. So did Gmap3 adding a simple context menu.

堆栈溢出问题Google 地图 v3 - 上下文菜单可用?4月份的也刚刚拿出了上面的例子。因此,没有Gmap3添加一个简单的上下文菜单

But maybe somebody has encapsulated the examples in a reusable library or found something in the meantime. Obviously there was somethingfor V2.

但也许有人已经将示例封装在一个可重用的库中,或者在此期间找到了一些东西。显然,V2有一些东西

-- Updated 2012-05-31 --

-- 更新 2012-05-31 --

I have found another one http://googlemapsmania.blogspot.de/2012/04/create-google-maps-context-menu.html, but did not have the time to test it yet.

我找到了另一个http://googlemapsmania.blogspot.de/2012/04/create-google-maps-context-menu.html,但还没有时间测试它。

回答by ShadeTreeDeveloper

I don't think you need a library for this. I'd start by trying:

我不认为你需要一个图书馆。我首先尝试:

var contextMenu = google.maps.event.addListener(
        map,
        "rightclick",
        function( event ) {
            // use JS Dom methods to create the menu
            // use event.pixel.x and event.pixel.y 
            // to position menu at mouse position
            console.log( event );
        }
    );

This assumes your map was created with:

这假设您的地图是通过以下方式创建的:

var map = new google.maps.map( { [map options] } );

The eventobject inside the callback has 4 properties

event回调中的对象有 4 个属性

  1. latLng
  2. ma
  3. pixel
  1. latLng
  2. ma
  3. pixel

where pixel.xand pixel.yare the offset where your click event triggered - counted from the upper left corner of the canvas holding the map object.

其中pixel.xpixel.y是您的点击事件触发的偏移量 - 从包含地图对象的画布的左上角开始计算。

回答by Faisal Mq

I have created a working JS Fiddle for showing context menu as well as the ability to have clickable items on this context menu.

我已经创建了一个有效的 JS Fiddle 来显示上下文菜单以及在这个上下文菜单上有可点击项目的能力。

It shows a clickable Context Menu when a marker is right clicked on Google map. Basically it makes use of an OverlayView on map. BTW its just a demo.

当在 Google 地图上右键单击标记时,它会显示一个可点击的上下文菜单。基本上它在地图上使用了一个 OverlayView。顺便说一句,它只是一个演示。

var loc, map, marker, contextMenu;

ContextMenu.prototype = new google.maps.OverlayView();

/**
  * onAdd is called when the map's panes are ready and the overlay has been
  * added to the map.
  */
ContextMenu.prototype.onAdd = function() {

    $("<div id='cMenu' class='context-menu-marker'></div>").appendTo(document.body);
    var divOuter = $("#cMenu").get(0);

    for(var i=0;i < this.menuItems.length;i++) {
        var mItem = this.menuItems[i];
        $('<div id="' + mItem.id + '" class="options-marker">' +
          mItem.label + '</div>').appendTo(divOuter);
    }

    this.div_ = divOuter;

    // Add the element to the "overlayLayer" pane.
    var panes = this.getPanes();
    //panes.overlayLayer.appendChild();
    panes.overlayMouseTarget.appendChild(this.div_);

    var me = this;

    for(var i=0;i < this.menuItems.length;i++) {
        var mItem = this.menuItems[i];

        var func = function() {
           me.clickedItem = this.id;
           google.maps.event.trigger(me, 'click');
        };

        google.maps.event.addDomListener($("#" + mItem.id).get(0), 'click', $.proxy(func, mItem));
    }


    google.maps.event.addListener(me, 'click', function() {
       alert(me.clickedItem); 
    });

};

ContextMenu.prototype.draw = function() {
    var div = this.div_;
    div.style.left = '0px';
    div.style.top = '0px';
    div.style.width = '100px';
    div.style.height = '50px';
};

// The onRemove() method will be called automatically from the API if
// we ever set the overlay's map property to 'null'.
ContextMenu.prototype.onRemove = function() {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
};

// Set the visibility to 'hidden' or 'visible'.
ContextMenu.prototype.hide = function() {
  if (this.div_) {
    // The visibility property must be a string enclosed in quotes.
    this.div_.style.visibility = 'hidden';
  }
};

ContextMenu.prototype.show = function(cpx) {
  if (this.div_) {
    var div = this.div_;
    div.style.left = cpx.x + 'px';
    div.style.top = cpx.y + 'px';

    this.div_.style.visibility = 'visible';
  }
};

function ContextMenu(map,options) {
    options = options || {}; //in case no options are passed to the constructor
    this.setMap(map); //tells the overlay which map it needs to draw on
    this.mapDiv = map.getDiv(); //Div container that the map exists in
    this.menuItems = options.menuItems || {}; //specific to context menus
    this.isVisible = false; //used to hide or show the context menu
}

function initialize() {

    loc = new google.maps.LatLng(62.323907, -150.109291);

    var options = {};
    var menuItems=[];

    menuItems.push({id:"zoomIn", className:'context_menu_item', eventName:'zoom_in_click', label:'Zoom in'});
    menuItems.push({id:"zoomOut", className:'context_menu_item', eventName:'zoom_out_click', label:'Zoom out'});


    options.menuItems = menuItems;
    //=========================================

    map = new google.maps.Map(document.getElementById("map"), {
        zoom: 12,
        center: loc,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    marker = new google.maps.Marker({
        map: map,
        position: loc,
        visible: true
    });

    contextMenu = new ContextMenu(map, options);

    google.maps.event.addListener(marker, 'rightclick', function(mouseEvent){
        contextMenu.hide();
        this.clickedMarker_ = this;
        var overlayProjection = contextMenu.getProjection();
        var cpx = overlayProjection.fromLatLngToContainerPixel(mouseEvent.latLng);
        contextMenu.show(cpx);

        map.setOptions({ draggableCursor: 'pointer' });
    });

    // Hide context menu on several events
    google.maps.event.addListener(map,'click', function(){
        map.setOptions({ draggableCursor: 'grab' });
        contextMenu.hide();
    });

}

google.maps.event.addDomListener(window, 'load', initialize);

Fiddle link:

小提琴链接:

http://jsfiddle.net/jEhJ3/3409/

http://jsfiddle.net/jEhJ3/3409/

回答by Bowei Liu

Go to this demo-purpose website: http://easysublease.org/mapcoverjs/

转到此演示目的网站:http: //easysublease.org/mapcoverjs/

For context menu, I do not suggest implementing one subclass of the overlayView Class provided by Google Maps API. First, one instance of subclass of overlayViewshould be added to the five panes provided by Google. More possibly one should add this instance to pane overlayMouseTarget. But, this instance is "shadowed" by other dom over it. So normal original browser event such mouseover, mouseoutcannot reach this instance.

对于上下文菜单,我不建议实现 Google Maps API 提供的 overlayView 类的一个子类。首先,overlayView应将 的一个子类实例添加到 Google 提供的五个窗格中。更有可能的是,应该将此实例添加到 pane overlayMouseTarget但是,这个实例被其他 dom “遮蔽”了。所以正常的原始浏览器事件mouseovermouseout无法到达这个实例。

One must use Google Maps API method: addDomListenerto handle it(why?). It requires lots of JavaScript code to implement different event handlers, do lots of css class adding and deleting just to realize some visual effects, which could be done using several lines of CSS code ifthis instance is outside the map container.

必须使用 Google Maps API 方法:addDomListener处理它(为什么?)。它需要大量的 JavaScript 代码来实现不同的事件处理程序,做大量的 css 类添加和删除只是为了实现一些视觉效果,如果这个实例在地图容器之外,可以使用几行 CSS 代码来完成。

So actually converting one external dom outside google map container into one context menu has merit that it can receive original DOM events from browser. Also using some external library can make the target behave better. As context menu, it should not only be able to handle original events, but also those events from Map.

因此,实际上将 google map 容器之外的一个外部 dom 转换为一个上下文菜单的优点是它可以从浏览器接收原始 DOM 事件。还使用一些外部库可以使目标表现得更好。作为上下文菜单,它不仅应该能够处理原始事件,还应该能够处理来自 Map 的事件。

-----------see implementations below------------------------

-----------见下面的实现------------------------

At the map part HTML, this is the code:

在地图部分 HTML,这是代码:

<div id="mapcover">
  <div id="mapcover-map"></div> <!-- this is map container-->
  <div id="demoControlPanel" class="mc-static2mapcontainer panel">I am map UI control button's container, I think one can use jQuery UI to make me look better<br><br>
    <div id="zoom-in-control" class="text-center">zoomIn</div>
    <div id="zoom-out-control" class="text-center">zoomOut</div>
  </div>
  <div id="demoContextPanel" class="mc-ascontextmenu panel">

    I am map context menu container, you can sytle me and add logic to me, just as normal DOM nodes.
    since I am not in Map Container at all! 
    <div class="text-center">
      <div role="group" aria-label="..." class="btn-group">
        <button id="place-marker1" type="button" class="btn btn-default">Marker1</button>
        <button id="place-marker2" type="button" class="btn btn-default">Marker2</button>
      </div>
    </div>
    <div class="form-group">
      <label for="content-marker1">Content of next Marker1</label>
      <input id="content-marker1" type="text" placeholder="New of Marker1!" class="form-control">
    </div>
  </div>
</div>

It shows how one developer can convert one external DOM (id=demoContextPanel) into one map context menu by just adding one css class ".mc-ascontextmenu"! That pages uses mapcover.js, which helps developer to manage some key components of Map such as Map control UIs, context menu, and customized markers. Then Developers have full freedom to style its map UIs.

它展示了一位开发人员如何通过添加一个 css 类“.mc-ascontextmenu”将一个外部 DOM (id=demoContextPanel) 转换为一个地图上下文菜单!该页面使用 mapcover.js,它可以帮助开发人员管理 Map 的一些关键组件,例如 Map 控件 UI、上下文菜单和自定义标记。然后开发人员可以完全自由地设计其地图 UI 的样式。

If you need more, you can go to its Github see readme.md: https://github.com/bovetliu/mapcover

如果您需要更多,你可以去它的Github上看到readme.md:https://github.com/bovetliu/mapcover

回答by Muhammad Ashhar Hasan

You can add context menu in google map by following these steps:

您可以按照以下步骤在谷歌地图中添加上下文菜单:

  1. Add a custom control, hide that control on page load (using css).
  2. Add a right click event handler on map.
  3. Show that custom control on right click at correct position using pixel property of right click event parameter.
  1. 添加自定义控件,在页面加载时隐藏该控件(使用 css)。
  2. 在地图上添加一个右键单击事件处理程序。
  3. 使用右键单击事件参数的像素属性在正确位置显示右键单击的自定义控件。

Following is working snippet (use you own key to avoid that google billing error):

以下是工作片段(使用您自己的密钥来避免谷歌计费错误):

var map;
var karachi = {
  lat: 24.8567575,
  lng: 66.9701725
};

$(document).ready(function() {
  initMap();
});

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 13.5,
    center: karachi
  });

  let contextMenu = document.getElementById('contextMenu');
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(contextMenu);
  hideContextMenu();

  google.maps.event.addListener(map, "rightclick", function(event) {
    showContextMenu(event);
  });
  google.maps.event.addListener(map, "click", function(event) {
    hideContextMenu();
  });
}

function showContextMenu(event) {
  $('#contextMenu').css("display", "block");
  $('#contextMenu').css({
    left: event.pixel.x,
    top: event.pixel.y
  })
}

function hideContextMenu() {
  $('#contextMenu').css("display", "none");
}
#map {
  height: 100%;
}
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

.contextMenu {
  background-color: rgb(255, 255, 255);
  border: 2px solid rgb(255, 255, 255);
  border-radius: 3px;
  box-shadow: rgba(0, 0, 0, 0.3) 0px 2px 6px;
  cursor: pointer;
  font-size: 1rem;
  text-align: center;
  color: #0d1f49;
  width: 20vw;
  margin: 1px;/*Please note that this margin is necessary otherwise browser will open its own context menu*/
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAGlM3LLIL2j4Wm-WQ9qUz7I7ZpBsUx1X8">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="map"></div>
<div id="contextMenu" class="contextMenu">
  <div onclick="alert('On click of item 1 is called')">
    Item 1
  </div>
</div>