Google Maps 鼠标右键菜单简易效果

因公司的需求,所以要使用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, "&nbsp;"); }) + "&nbsp;&nbsp;<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>

电脑维修网

原文地址:https://www.cnblogs.com/frlmoney/p/2997629.html