因公司的需求,所以要使用Google Maps做一些应用。实际当中鼠标右键弹出菜单并进行必要的操作,该功能是必不可少的。Google过后现成的资料很少。唯一找到一篇能用的就是园子里的这篇文章,大家可以参考一下http://www.cnblogs.com/zxy900213/archive/2011/12/09/zxy_map.html (网上有很多转贴,我也分不清楚到底哪个是原帖。这个帖子是我第一次找到,暂且就当其为原帖吧)
首先说下该帖子存在的BUG。
1、当鼠标移动到Google Maps左上角缩放控件时,并移出弹出菜单会根据google.maps.ControlPosition.TOP重新定位。
2、删除标记描述时没有做判断,对象为null时会报错。主要表现在未添加描述时直接点击“删除描述”或者添加描述后连续删除2次时会报错。
3、作者指出在IE以外的浏览器使用鼠标的x和y坐标弹出菜单时会出现偏移,需要另外计算。因此在Chrome中效率比IE中低,直接在Firefox中,鼠标右键标记(Marker)没有任何效果。
4、鼠标右键弹出菜单,始终根据鼠标点做绝对定位,因此滑倒浏览器下侧,弹出层绝大部分会被浏览器遮盖。
由于第三条BUG使我放弃了对于该文代码的重构工作。打算还是仿Google Maps 效果做一个Demo。国内的网站盗版很容易,韩国网站和类似于Google这种大公司的盗版工作是挺难的,因此必要的时候还是需要下点功夫的。盗版成功后,代码会在今后的博文中贴出。现在盗版过程中发现的难点就在于Google Maps中鼠标右键触发的点始终找不到,有兴趣的兄弟可以试着一起找找。
下边就把重构到一半的代码贴出来供大家学习,在实际项目中不推荐使用。如果发现修复这些BUG的方法,希望能够与您一起讨论讨论。
贴出该代码的用意实在了解JavaScript框架的搭建,以及重构。对于学习JavaScript框架有着重要的帮助。用例比较简单容易看懂,对今后学习jQuery或ExtJS有很大的帮助。成熟的框架更为高深,想进阶学习JavaScript直接参照jQuery或ExtJS源码即可。
CSS:
<style type="text/css"> html { height: 100%; } body { height: 100%; margin: 0; padding: 0; font-size: 13px; padding-top: 1px !important; } #map_canvas { height: 100%; } /*Google Maps 样式*/ .kd-menulist { background: none repeat scroll 0 0 #FFFFFF; border: 1px solid #CCCCCC; padding: 0 0 6px; position: absolute; white-space: nowrap; z-index: 1000; } .kd-menulist { border: medium none; outline: 1px solid rgba(0, 0, 0, 0.2); } .kd-menulistitem { color: #333333; display: block; font-weight: normal; padding: 6px 44px 6px 16px; position: relative; } .kd-menulistitem.disable, .kd-menulistitem.disable:hover, .kd-menulistitem.disable { background-color: #FFFFFF; color: #CCCCCC; cursor: default; } .kd-menulistitem:hover, .kd-menulistitem.selected { background-color: #F1F1F1; color: #222222; } .kd-menurule { border-top: 1px solid #EBEBEB; margin-bottom: 10px; margin-top: 9px; } </style>
JavaScript:
Array.prototype.remove = function (item) { for (var i = 0; i < this.length; i++) { if (this[i] == item) { this.splice(i, 1); } } } Array.prototype.getItem = function (id) { for (var i = 0; i < this.length; i++) { if (this[i].identity == id) { return this[i]; } } } function MenuItem(options) { options = options || {}; this.text = options.text || ""; this.handler = options.handler; this.groupName = options.groupName; this.host = null; //宿主 this.casing = document.createElement("div"); this.casing.className = "kd-menulistitem"; this.casing.innerHTML = this.text; var self = this; if (typeof self.handler == "function") { google.maps.event.addDomListener(self.casing, "click", function () { if (self.host) { self.handler(self.host.coordinate); self.host.hide(); } }); } } function MenuControl(map) { this.container = document.createElement("div"); this.coordinate = null; this.map = map; this.sender = null; this.isEnable = true; this.container.className = "kd-menulist"; this.hide(); this.items = new Array(); this.markers = new Array(); var self = this; google.maps.event.addListener(map, "click", function () {//点击 self.hide(); }); google.maps.event.addListener(map, "movestart", function () {// self.hide(); }); google.maps.event.addListener(map, "zoom_changed", function () {//尺寸缩放 self.hide(); }); google.maps.event.addListener(map, "dragstart", function () {//鼠标拖动 self.hide(); }); //https://developers.google.com/maps/documentation/javascript/controls?hl=zh-cn#CustomPositioning //自定义控件示例 this.container.index = 1; map.controls[google.maps.ControlPosition.TOP].push(this.container); //主地图鼠标右键菜单 self.addItem(new MenuItem({ text: "添加标记", groupName: "map", handler: function (myLatlng) { if (self.markers.length >= 5) { alert("最多能添加5个标记!"); } else { var marker = new google.maps.Marker({ position: myLatlng.latlng, map: map, draggable: true }); marker.identity = identity++; // 添加标记的右击事件,弹出菜单时,IE以外的浏览器会出现偏移 google.maps.event.addListener(marker, "rightclick", function (e) { self.sender = marker; if (self.isEnable) { var x = e.pixel.x; var y = e.pixel.y; if (document.all) { x = window.event.x; y = window.event.y; } else { // 在IE以外的浏览器使用鼠标的x和y坐标弹出菜单时会出现偏移,需要另外计算 var eve = window.event; if (!eve) { var c = rightclick; do { var arg0 = c.arguments[0]; if (arg0) { if (arg0.constructor == MouseEvent) { eve = arg0; break; } } c = c.caller; } while (c.caller) } var scale = Math.pow(2, map.getZoom()); var bounds = map.getBounds(); var nw = new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getSouthWest().lng()); var point = map.getProjection().fromLatLngToPoint(nw); var worldCoor = map.getProjection().fromLatLngToPoint(marker.getPosition()); var off = new google.maps.Point(Math.floor((worldCoor.x - point.x) * scale), Math.floor((worldCoor.y - point.y) * scale)); var markerImg = eve.target.parentNode.parentNode.childNodes[0]; x = (off.x - (markerImg.offsetWidth) / 2) + eve.layerX; y = (off.y - markerImg.offsetHeight) + eve.layerY; } self.coordinate = { point: new google.maps.Point(x, y), latlng: myLatlng.latlng }; self.container.style.left = x + "px"; self.container.style.top = y + "px"; self.show("marker"); } }); google.maps.event.addListener(marker, "click", function (e) { self.sender = marker; if (!self.sender.info) { self.sender.info = new google.maps.InfoWindow({ content: marker.description + ":" + marker.identity }); } self.sender.info.open(map, marker); }); self.markers.push(marker); } } })); self.addItem(new MenuItem({ text: "清除所有标记", groupName: "map", handler: function (myLatlng) { if (self.markers) { for (var i = 0; i < self.markers.length; i++) { self.markers[i].setMap(null); } self.markers.length = 0; } } })); self.addSeparator("map"); self.addItem(new MenuItem({ text: "放大", groupName: "map", handler: function (myLatlng) { map.setZoom(map.getZoom() + 1); } })); self.addItem(new MenuItem({ text: "缩小", groupName: "map", handler: function (myLatlng) { map.setZoom(map.getZoom() - 1); } })); self.addItem(new MenuItem({ text: "在此居中放置地图", groupName: "map", handler: function (myLatlng) { map.setCenter(myLatlng.latlng); } })); //标记鼠标右键菜单 self.addItem(new MenuItem({ text: "清除该标记", groupName: "marker", handler: function (myLatlng) { self.sender.setMap(null); self.markers.remove(self.sender); } })); self.addSeparator("marker"); self.addItem(new MenuItem({ text: "添加描述", groupName: "marker", handler: function (myLatlng) { var marker = self.sender; if (!marker.win) { marker.win = new google.maps.InfoWindow({ content: "<textarea onblur=\"edited(this," + marker.identity + ");\" rows=\"3\" cols=\"22\"></textarea>" }); google.maps.event.addListener(marker, "click", function () { if (marker.win) marker.win.open(map, marker); }); marker.description = ""; } marker.win.setContent("<textarea onblur=\"edited(this," + marker.identity + ");\" rows=\"3\" cols=\"22\">" + marker.description + "</textarea>") marker.win.open(map, marker); } })); self.addItem(new MenuItem({ text: "删除描述", groupName: "marker", handler: function (myLatlng) { if (self.sender.win != null) {//判断一下,否则第二次删除描述时报错 self.sender.win.close(); self.sender.win = null; } } })); } MenuControl.prototype.show = function (groupName) { this.container.style.display = "block"; if (groupName) { for (var i = 0; i < this.items.length; i++) { if (groupName == this.items[i].groupName) { this.items[i].casing.style.display = "block"; } else { this.items[i].casing.style.display = "none"; } } } } MenuControl.prototype.hide = function (groupName) { this.container.style.display = "none"; if (groupName) { for (var i = 0; i < this.items.length; i++) { if (groupName == this.items[i].groupName) { this.items[i].hide(); } else { this.items[i].show(); } } } } MenuControl.prototype.MenuSeparator = function (groupName) { this.groupName = groupName; this.casing = document.createElement("div"); this.casing.className = "kd-menurule"; } MenuControl.prototype.addItem = function (item) { item.host = this; this.items.push(item); this.container.appendChild(item.casing); } MenuControl.prototype.addSeparator = function (group) { var separator = group || new this.MenuSeparator(); if (typeof group == "string") { separator = new this.MenuSeparator(group); } this.items.push(separator); this.container.appendChild(separator.casing); }
HTML:
<script type="text/javascript"> //原文地址 //http://www.cnblogs.com/zxy900213/archive/2011/12/09/zxy_map.html var menu var map; //var markers = new Array(); var identity = 0; function initialize() { var myLatlng = new google.maps.LatLng(23.129163, 113.264435); map = new google.maps.Map(document.getElementById("map_canvas"), { zoom: 12, center: myLatlng, mapTypeId: google.maps.MapTypeId.HYBRID }); menu = new MenuControl(map); //menu.sender = map; google.maps.event.addListener(map, "rightclick", function (e) { if (menu.isEnable) { menu.coordinate = { point: e.pixel, latlng: e.latLng }; menu.container.style.left = e.pixel.x + "px"; menu.container.style.top = e.pixel.y + "px"; menu.show("map"); } }); } self.edited = function (sender, id) { var marker = menu.markers.getItem(id); marker.win.setContent(sender.value.replace(/[\r\n]/g, "<br/>").replace(/>([^<>]+)((?=<)|$)/g, function (t) { return t.replace(/[\s]/g, " "); }) + " <a href=\"javascript:;\" onclick=\"edit(" + id + ");\">编辑</a>"); marker.description = sender.value; } self.edit = function (id) { var marker = menu.markers.getItem(id); marker.win.setContent("<textarea onblur=\"edited(this," + id + ");\" rows=\"3\" cols=\"22\">" + marker.description + "</textarea>"); } </script> <body onload="initialize()"> <div id="map_canvas" style="height: 100%;"> </div> </body>