web-dev-qa-db-ja.com

Google MapV3のコンテキストメニュー

Google MapV3のコンテキストメニューライブラリを探しています。ここでいくつかのコード例を見つけました

  1. Gizzmoのブログ
  2. Google APIのヒント
  3. GMap
  4. どうやって..

スタックオーバーフローの質問 Googleマップv3-コンテキストメニューが利用可能ですか? 4月も上記の例を思いついたところです。そうだった Gmap3は簡単なコンテキストメニューを追加する

しかし、誰かが例を再利用可能なライブラリにカプセル化したか、その間に何かを見つけた可能性があります。明らかに、V2には 何か がありました。

-2012年5月31日更新-

別のものを見つけました http://googlemapsmania.blogspot.de/2012/04/create-google-maps-context-menu.html ですが、まだテストする時間がありませんでした。

13
Horst Walter

このためのライブラリは必要ないと思います。私は試すことから始めます:

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

どこ pixel.xおよびpixel.yは、クリックイベントがトリガーされたオフセットです-マップオブジェクトを保持しているキャンバスの左上隅から数えます。

10

コンテキストメニューを表示するための実用的なJS Fiddleと、このコンテキストメニューにクリック可能なアイテムを表示する機能を作成しました。

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

フィドルリンク:

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

3
Faisal Mq

このデモ目的のWebサイトにアクセスします: http://easysublease.org/mapcoverjs/

コンテキストメニューの場合、Google MapsAPIによって提供されるoverlayViewクラスの1つのサブクラスを実装することはお勧めしません。まず、overlayViewのサブクラスの1つのインスタンスをGoogleが提供する5つのペインに追加する必要があります。おそらく、このインスタンスをペインoverlayMouseTargetに追加する必要があります。 しかし、このインスタンスは他のdomによって「シャドウ」されています。したがって、mouseovermouseoutなどの通常の元のブラウザイベントはこのインスタンスに到達できません。

Google Maps APIメソッドを使用する必要があります:addDomListenerそれを処理する( なぜ? )。さまざまなイベントハンドラーを実装するために多くのJavaScriptコードが必要であり、視覚効果を実現するためだけに多くのcssクラスの追加と削除を行います。これは、CSSコードの数行を使用して実行できますifこのインスタンスはマップコンテナの外にあります。

したがって、実際にGoogleマップコンテナの外部にある1つの外部DOMを1つのコンテキストメニューに変換することには、ブラウザから元のDOMイベントを受信できるというメリットがあります。また、外部ライブラリを使用すると、ターゲットの動作を改善できます。コンテキストメニューとして、元のイベントだけでなく、マップからのイベントも処理できる必要があります。

-----------以下の実装を参照してください------------------------

マップ部分の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>

これは、1人の開発者が1つのcssクラス「.mc-ascontextmenu」を追加するだけで、1つの外部DOM(id = demoContextPanel)を1つのマップコンテキストメニューに変換する方法を示しています。そのページはmapcover.jsを使用します。これは、開発者がマップコントロールUI、コンテキストメニュー、カスタマイズされたマーカーなど、マップのいくつかの主要コンポーネントを管理するのに役立ちます。そうすれば、開発者はマップUIのスタイルを自由に設定できます。

さらに必要な場合は、Githubにアクセスしてreadme.mdを参照してください: https://github.com/bovetliu/mapcover

1
Bowei Liu

次の手順に従って、Googleマップにコンテキストメニューを追加できます。

  1. カスタムコントロールを追加し、ページの読み込み時にそのコントロールを非表示にします(cssを使用)。
  2. マップ上に右クリックイベントハンドラーを追加します。
  3. 右クリックイベントパラメータのピクセルプロパティを使用して、正しい位置で右クリックのカスタムコントロールを表示します。

以下は作業スニペットです(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>