Google Map V3上下文菜单

时间:2011-08-23 22:40:30

标签: javascript google-maps-api-3 contextmenu

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

  1. Gizzmo's blog
  2. Google API tips
  3. GMap3
  4. How I got ..
  5. 四月的堆栈溢出问题Google maps v3 - Contextual menu available?也刚刚提出了上面的例子。 Gmap3 adding a simple context menu也是如此。

    但也许有人将这些例子封装在一个可重用的库中,或者在此期间发现了一些东西。 V2显然有something

    - 2012-05-31更新 -

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

4 个答案:

答案 0 :(得分:8)

我认为你不需要这个库。我首先尝试:

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 );
        }
    );

这假定您的地图是使用以下内容创建的:

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

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

  1. latLng
  2. ma
  3. pixel
  4. 其中pixel.xpixel.y是点击事件触发的偏移量 - 从持有地图对象的画布的左上角开始计算。

答案 1 :(得分:3)

我创建了一个有效的JS Fiddle,用于显示上下文菜单以及在此上下文菜单中具有可点击项的功能。

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

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);

小提琴链接:

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

答案 2 :(得分:2)

您可以按照以下步骤在Google地图中轻松添加上下文菜单:

  1. 添加Google地图的自定义控件,在页面加载时隐藏该控件。
  2. 在地图上添加右键单击事件处理程序。
  3. 使用右键事件参数的pixel属性在正确的位置上右键单击显示自定义控件。

此外,以下是有效的代码段,请全页打开(使用您自己的密钥来避免该Google结算错误):

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>

答案 3 :(得分:1)

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

对于上下文菜单,我不建议实现Google Maps API提供的overlayView类的一个子类。首先,应将overlayView的子类的一个实例添加到Google提供的五个窗格中。更有可能应该将此实例添加到窗格overlayMouseTarget但是,这个实例是&#34;阴影&#34;通过其他dom。因此,正常的原始浏览器事件mouseovermouseout无法访问此实例。

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

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

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

在地图部分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>

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

如果您需要更多,可以访问其Github,请参阅readme.md:https://github.com/bovetliu/mapcover