zoukankan      html  css  js  c++  java
  • 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>

    电脑维修网

  • 相关阅读:
    【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)
    【洛谷 P4289】[HAOI2008]移动玩具(搜索)
    【洛谷 SP283】NAPTIME
    【洛谷 P4342】[IOI1998]Polygon(DP)
    【洛谷 SP2878】Knights of the Round Table(双联通分量)
    【洛谷 P4168】[Violet]蒲公英(分块)
    【洛谷 P4180】【模板】严格次小生成树[BJWC2010](倍增)
    数学总结
    个人码风
    【洛谷 P3304】[SDOI2013]直径(树的直径)
  • 原文地址:https://www.cnblogs.com/frlmoney/p/2997629.html
Copyright © 2011-2022 走看看