首先声明感谢http://google-maps-utility-library-v3.googlecode.com/svn/tags/keydragzoom/1.0/docs/examples.html的作者,我参考他的keydragzoom,修改了他的源码完成了我的dragzoomcontrol。
?
先介绍一下DragZoomControl,简单的很就是在第三版的Google Map中,添加一个按钮,点击“DragZoom”按钮后进行框选操作,框选完成后可以跟后台进行Ajax交互,这里的例子是将框选的southwest和northeast传给后台再传到前台。(有点无聊)。
?
然后就是贴上代码:
?
dragzoomcontrol.js:
?
(function () { /** * Converts 'thin', 'medium', and 'thick' to pixel widths * in an MSIE environment. Not called for other browsers * because getComputedStyle() returns pixel widths automatically. * @param {String} widthValue */ var toPixels = function (widthValue) { var px; switch (widthValue) { case 'thin': px = "2px"; break; case 'medium': px = "4px"; break; case 'thick': px = "6px"; break; default: px = widthValue; } return px; }; /** * Get the widths of the borders of an HTML element. * * @param {Object} h HTML element * @return {Object} widths object (top, bottom left, right) */ var getBorderWidths = function (h) { var computedStyle; var bw = {}; if (document.defaultView && document.defaultView.getComputedStyle) { computedStyle = h.ownerDocument.defaultView.getComputedStyle(h, ""); if (computedStyle) { // The computed styles are always in pixel units (good!) bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0; bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0; bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0; return bw; } } else if (document.documentElement.currentStyle) { // MSIE if (h.currentStyle) { // The current styles may not be in pixel units so try to convert (bad!) bw.top = parseInt(toPixels(h.currentStyle.borderTopWidth), 10) || 0; bw.bottom = parseInt(toPixels(h.currentStyle.borderBottomWidth), 10) || 0; bw.left = parseInt(toPixels(h.currentStyle.borderLeftWidth), 10) || 0; bw.right = parseInt(toPixels(h.currentStyle.borderRightWidth), 10) || 0; return bw; } } // Shouldn't get this far for any modern browser bw.top = parseInt(h.style["border-top-width"], 10) || 0; bw.bottom = parseInt(h.style["border-bottom-width"], 10) || 0; bw.left = parseInt(h.style["border-left-width"], 10) || 0; bw.right = parseInt(h.style["border-right-width"], 10) || 0; return bw; }; /** * Get the position of the mouse relative to the document. * @param {Object} e Mouse event * @return {Object} left & top position */ var getMousePosition = function (e) { var posX = 0, posY = 0; e = e || window.event; if (typeof e.pageX !== "undefined") { posX = e.pageX; posY = e.pageY; } else if (typeof e.clientX !== "undefined") { posX = e.clientX + (typeof document.documentElement.scrollLeft !== "undefined" ? document.documentElement.scrollLeft : document.body.scrollLeft); posY = e.clientY + (typeof document.documentElement.scrollTop !== "undefined" ? document.documentElement.scrollTop : document.body.scrollTop); } return { left: posX, top: posY }; }; /** * Get the position of an HTML element relative to the document. * @param {Object} h HTML element * @return {Object} left & top position */ var getElementPosition = function (h) { var posX = h.offsetLeft; var posY = h.offsetTop; var parent = h.offsetParent; // Add offsets for all ancestors in the hierarchy while (parent !== null) { // Adjust for scrolling elements which may affect the map position. if (parent !== document.body && parent !== document.documentElement) { posX -= parent.scrollLeft; posY -= parent.scrollTop; } posX += parent.offsetLeft; posY += parent.offsetTop; parent = parent.offsetParent; } return { left: posX, top: posY }; }; /** * Set the properties of an object to those from another object. * @param {Object} obj target object * @param {Object} vals source object */ var setVals = function (obj, vals) { if (obj && vals) { for (var x in vals) { if (vals.hasOwnProperty(x)) { obj[x] = vals[x]; } } } return obj; }; /** * Set the opacity. If op is not passed in, this function just performs an MSIE fix. * @param {Node} div * @param {Number} op (0-1) */ var setOpacity = function (div, op) { if (typeof op !== 'undefined') { div.style.opacity = op; } if (typeof div.style.opacity !== 'undefined') { div.style.filter = "alpha(opacity=" + (div.style.opacity * 100) + ")"; } }; function DragZoom(map, opt_zoomOpts) { var ov = new google.maps.OverlayView(); var me = this; ov.onAdd = function () { me.init_(map, opt_zoomOpts); }; ov.draw = function () { }; ov.onRemove = function () { }; ov.setMap(map); this.prjov_ = ov; } /** * Init the tool. */ DragZoom.prototype.init_ = function (map, opt_zoomOpts) { // Set CSS styles for the DIV containing the control this.controlDiv_=opt_zoomOpts.controlDiv; this.controlDiv_.style.paddingTop = '5px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = '#FFFFFF'; controlUI.style.borderColor = '#717B87'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '1px'; controlUI.style.boxShadow = '1px 2px 4px #888888'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = 'Click to Active the map DragZoom'; this.controlDiv_.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingBottom = '1px'; controlText.style.paddingLeft = '4px'; controlText.style.paddingRight = '4px'; controlText.style.paddingTop = '1px'; controlText.innerHTML = 'DragZoom'; controlUI.appendChild(controlText); this.map_ = map; opt_zoomOpts = opt_zoomOpts || {}; this.borderWidths_ = getBorderWidths(this.map_.getDiv());//Container()); this.paneDiv_ = document.createElement("div"); this.paneDiv_.onselectstart = function () { return false; }; // default style setVals(this.paneDiv_.style, { backgroundColor: 'white', opacity: 0.0, cursor: 'crosshair' }); // allow overwrite setVals(this.paneDiv_.style, opt_zoomOpts.paneStyle); // stuff that cannot be overwritten setVals(this.paneDiv_.style, { position: 'absolute', overflow: 'hidden', zIndex: 10001, display: 'none' }); setOpacity(this.paneDiv_); // An IE fix: if the background is transparent, it cannot capture mousedown events if (this.paneDiv_.style.backgroundColor === 'transparent') { this.paneDiv_.style.backgroundColor = 'white'; setOpacity(this.paneDiv_, 0); } this.map_.getDiv().appendChild(this.paneDiv_);//Container() this.boxDiv_ = document.createElement('div'); setVals(this.boxDiv_.style, { border: 'thin solid #FF0000' }); setVals(this.boxDiv_.style, opt_zoomOpts.boxStyle); setVals(this.boxDiv_.style, { position: 'absolute', display: 'none' }); setOpacity(this.boxDiv_); this.map_.getDiv().appendChild(this.boxDiv_); this.boxBorderWidths_ = getBorderWidths(this.boxDiv_); var me = this; this.controlUIDownListener_ = google.maps.event.addDomListener(controlUI, 'click', function() { me.onControlUIClick_(); }); this.mouseDownListener_ = google.maps.event.addDomListener(this.paneDiv_, 'mousedown', function (e) { me.onMouseDown_(e); }); this.mouseDownListenerDocument_ = google.maps.event.addDomListener(document, 'mousedown', function (e) { me.onMouseDownDocument_(e); }); this.mouseMoveListener_ = google.maps.event.addDomListener(document, 'mousemove', function (e) { me.onMouseMove_(e); }); this.mouseUpListener_ = google.maps.event.addDomListener(document, 'mouseup', function (e) { me.onMouseUp_(e); }); this.controlUIDown_ = false; this.dragging_ = false; this.startPt_ = null; this.endPt_ = null; this.boxMaxX_ = null; this.boxMaxY_ = null; this.mousePosn_ = null; this.mapPosn_ = getElementPosition(this.map_.getDiv()); this.mouseDown_ = false; }; /** * Checks if the mouse is on top of the map. The position is captured * in onMouseMove_. * @return true if mouse is on top of the map div. */ DragZoom.prototype.isMouseOnMap_ = function () { var mousePos = this.mousePosn_; if (mousePos) { var mapPos = this.mapPosn_; var mapDiv = this.map_.getDiv(); return mousePos.left > mapPos.left && mousePos.left < mapPos.left + mapDiv.offsetWidth && mousePos.top > mapPos.top && mousePos.top < mapPos.top + mapDiv.offsetHeight; } else { // if user never moved mouse return false; } }; /** * Show or hide the overlay pane, depending on whether the mouse is over the map. */ DragZoom.prototype.setPaneVisibility_ = function () { if (this.map_ && this.controlUIDown_ && this.isMouseOnMap_()) { //alert("setPaneVisibility_"); var mapDiv = this.map_.getDiv(); this.paneDiv_.style.left = 0 + 'px'; this.paneDiv_.style.top = 0 + 'px'; this.paneDiv_.style.width = mapDiv.offsetWidth - (this.borderWidths_.left + this.borderWidths_.right) + 'px'; this.paneDiv_.style.height = mapDiv.offsetHeight - (this.borderWidths_.top + this.borderWidths_.bottom) + 'px'; this.paneDiv_.style.display = 'block'; this.boxMaxX_ = parseInt(this.paneDiv_.style.width, 10) - (this.boxBorderWidths_.left + this.boxBorderWidths_.right); this.boxMaxY_ = parseInt(this.paneDiv_.style.height, 10) - (this.boxBorderWidths_.top + this.boxBorderWidths_.bottom); } else { this.paneDiv_.style.display = 'none'; } }; DragZoom.prototype.onControlUIClick_ = function () { if (this.map_ && !this.controlUIDown_) { //alert("onControlUIDown_"); this.controlUIDown_ = true; this.controlDiv_.childNodes.item(0).style.backgroundColor = '#E8E8E8'; this.controlDiv_.childNodes.item(0).childNodes.item(0).style.fontWeight = 'bold'; this.setPaneVisibility_(); /** * This event is fired when the ControlUI button is pressed. * @name DragZoom#activate * @event */ google.maps.event.trigger(me, 'activate'); }else { alert("onControlUIUp_"); this.controlUIDown_ = false; this.dragging_ = false; this.controlDiv_.childNodes.item(0).style.backgroundColor = '#FFFFFF'; this.controlDiv_.childNodes.item(0).childNodes.item(0).style.fontWeight = 'normal'; this.boxDiv_.style.display = 'none'; this.paneDiv_.style.display = "none"; /** * This event is fired while the user release the controlUI * @name DragZoom#deactivate * @event */ google.maps.event.trigger(this, 'deactivate'); } }; /** * Get the <code>google.maps.Point</code> of the mouse position. * @param {Object} e * @return {google.maps.Point} point * @private */ DragZoom.prototype.getMousePoint_ = function (e) { var mousePosn = getMousePosition(e); var p = new google.maps.Point(); p.x = mousePosn.left - this.mapPosn_.left - this.borderWidths_.left; p.y = mousePosn.top - this.mapPosn_.top - this.borderWidths_.top; p.x = Math.min(p.x, this.boxMaxX_); p.y = Math.min(p.y, this.boxMaxY_); p.x = Math.max(p.x, 0); p.y = Math.max(p.y, 0); return p; }; /** * Handle mouse down. * @param {Event} e */ DragZoom.prototype.onMouseDown_ = function (e) { if (this.map_ && this.controlUIDown_) { this.mapPosn_ = getElementPosition(this.map_.getDiv()); this.dragging_ = true; this.startPt_ = this.endPt_ = this.getMousePoint_(e); var prj = this.prjov_.getProjection(); var latlng = prj.fromDivPixelToLatLng(this.startPt_); /** * This event is fired when the drag operation begins. * @name DragZoom#dragstart * @param {GLatLng} startLatLng * @event */ google.maps.event.trigger(this, 'dragstart', latlng); } }; /** * Handle mouse down at the document level. * @param {Event} e */ DragZoom.prototype.onMouseDownDocument_ = function (e) { this.mouseDown_ = true; }; /** * Handle mouse move. * @param {Event} e */ DragZoom.prototype.onMouseMove_ = function (e) { this.mousePosn_ = getMousePosition(e); if (this.dragging_) { this.endPt_ = this.getMousePoint_(e); var left = Math.min(this.startPt_.x, this.endPt_.x); var top = Math.min(this.startPt_.y, this.endPt_.y); var width = Math.abs(this.startPt_.x - this.endPt_.x); var height = Math.abs(this.startPt_.y - this.endPt_.y); this.boxDiv_.style.left = left + 'px'; this.boxDiv_.style.top = top + 'px'; this.boxDiv_.style.width = width + 'px'; this.boxDiv_.style.height = height + 'px'; this.boxDiv_.style.display = 'block'; /** * This event is repeatedly fired while the user drags the box. The southwest and northeast * point are passed as parameters of type <code>google.maps.Point</code> (for performance reasons), * relative to the map container. Note: the event listener is responsible * for converting Pixel to LatLng, if necessary. * @name DragZoom#drag * @param {google.maps.Point} southwestPixel * @param {google.maps.Point} northeastPixel * @event */ google.maps.event.trigger(this, 'drag', new google.maps.Point(left, top + height), new google.maps.Point(left + width, top)); } else if (!this.mouseDown_) { this.setPaneVisibility_(); } }; /** * Handle mouse up. * @param {Event} e */ DragZoom.prototype.onMouseUp_ = function (e) { this.mouseDown_ = false; if (this.dragging_) { var left = Math.min(this.startPt_.x, this.endPt_.x); var top = Math.min(this.startPt_.y, this.endPt_.y); var width = Math.abs(this.startPt_.x - this.endPt_.x); var height = Math.abs(this.startPt_.y - this.endPt_.y); var prj = this.prjov_.getProjection(); // 2009-05-29: since V3 does not have fromContainerPixel, var containerPos = getElementPosition(this.map_.getDiv()); var mapPanePos = getElementPosition(this.prjov_.getPanes().mapPane); left = left + (containerPos.left - mapPanePos.left); top = top + (containerPos.top - mapPanePos.top); var sw = prj.fromDivPixelToLatLng(new google.maps.Point(left, top + height)); var ne = prj.fromDivPixelToLatLng(new google.maps.Point(left + width, top)); var bnds = new google.maps.LatLngBounds(sw, ne); this.map_.fitBounds(bnds); this.controlUIDown_ = false; this.dragging_ = false; this.controlDiv_.childNodes.item(0).style.backgroundColor = '#FFFFFF'; this.controlDiv_.childNodes.item(0).childNodes.item(0).style.fontWeight = 'normal'; this.boxDiv_.style.display = 'none'; /** * This event is fired when the drag operation ends. * Note that the event is not fired if the hot key is released before the drag operation ends. * @name DragZoom#dragend * @param {GLatLngBounds} newBounds * @event */ google.maps.event.trigger(this, 'dragend', bnds); } }; /** * @name google.maps.Map * @class These are new methods added to the Google Maps API's * <a href = 'http://code.google.com/apis/maps/documentation/v3/reference.html#Map'>Map</a> * class. */ /** * Enable drag zoom. The user can zoom to an area of interest by holding down the hot key * <code>(shift | ctrl | alt )</code> while dragging a box around the area. * @param {KeyDragZoomOptions} opt_zoomOpts */ google.maps.Map.prototype.enableKeyDragZoom = function (opt_zoomOpts) { this.dragZoom_ = new DragZoom(this, opt_zoomOpts); }; /** * Disable drag zoom. */ google.maps.Map.prototype.disableKeyDragZoom = function () { var d = this.dragZoom_; if (d) { alert("disableKeyDragZoom"); google.maps.event.removeListener(d.mouseDownListener_); google.maps.event.removeListener(d.mouseDownListenerDocument_); google.maps.event.removeListener(d.mouseMoveListener_); google.maps.event.removeListener(d.mouseUpListener_); google.maps.event.removeListener(d.controlUIDownListener_); google.maps.event.removeListener(d.controlUIUpListener_); this.getDiv().removeChild(d.boxDiv_); this.getDiv().removeChild(d.paneDiv_); this.dragZoom_ = null; } }; /** * Returns true if the drag zoom feature has been enabled. * @return {Boolean} */ google.maps.Map.prototype.keyDragZoomEnabled = function () { return this.dragZoom_ !== null; }; /** * Returns the DragZoom object which is created when <code>google.maps.Map.enableKeyDragZoom</code> is called. * With this object you can use <code>google.maps.event.addListener</code> to attach event listeners * for the 'activate', 'deactivate', 'dragstart', 'drag', and 'dragend' events. * @return {DragZoom} */ google.maps.Map.prototype.getDragZoomObject = function () { return this.dragZoom_; }; })();
?index.jsp:
?
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <style> #map { width: 700px; height: 400px; } </style> <script type="text/javascript" src="js/jquery-1.7.min.js"></script> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> <script type="text/javascript" src="js/dragzoomcontrol.js"></script> <script type="text/javascript"> var map; var markersArray = []; var center = new google.maps.LatLng(30.67, 104.06); function init() { var myOptions = { zoom: 13, center: center, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map"), myOptions); // Create the DIV to hold the control and // call the DragZoomControl() constructor passing in this DIV. var dragZoomControlDiv = document.createElement('DIV'); dragZoomControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(dragZoomControlDiv); map.enableKeyDragZoom({ controlDiv: dragZoomControlDiv, boxStyle: { opacity: 0.7 }, paneStyle: { backgroundColor: "gray", opacity: 0.1 } }); var dz = map.getDragZoomObject(); google.maps.event.addListener(dz, 'activate', function() { log('DragZoom Activated'); }); google.maps.event.addListener(dz, 'dragstart', function(latlng) { log('DragZoom Started: ' + latlng); }); google.maps.event.addListener(dz, 'drag', function(start, end) { //log('DragZoom Dragging...' + start + end); }); google.maps.event.addListener(dz, 'dragend', function(bnds) { log('DragZoom DragEnd :' + bnds); $.ajax({ url: 'AjaxMap', type: 'post', dataType: 'json', data: { swlat: bnds.getSouthWest().lat(), swlng: bnds.getSouthWest().lng(), nelat: bnds.getNorthEast().lat(), nelng: bnds.getNorthEast().lng() }, success: function(jsonMsg){ //var json = [eval('(' +jsonMsg +')')]; var json=jsonMsg; var sw = new google.maps.LatLng(json.swlat, json.swlng); var ne = new google.maps.LatLng(json.nelat, json.nelng); deleteOverlays(); addMarker(sw); addMarker(ne); } }); }); google.maps.event.addListener(dz, 'deactivate', function() { log('DragZoom Deactivated'); }); } function addMarker(location) { marker = new google.maps.Marker({ position: location, map: map, title: "Hello World" }); markersArray.push(marker); } function deleteOverlays() { if (markersArray) { for (i in markersArray) { markersArray[i].setMap(null); } markersArray.length = 0; } } function log(msg){ $("#msg").html($("#msg").html()+"<br/>"+msg); //document.getElementById('msg').innerHTML +="<br/>"+msg; } </script> </head> <body onload="init()"> <div id="map"></div> <br/> <div id="msg"></div> </body> </html>
?后台的servlet:
?
package com.wujay; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.simple.JSONObject; public class AjaxMap extends HttpServlet { public AjaxMap() { super(); } public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=gbk"); PrintWriter out=response.getWriter(); String swlat=request.getParameter("swlat"); String swlng=request.getParameter("swlng"); String nelat=request.getParameter("nelat"); String nelng=request.getParameter("nelng"); JSONObject obj=new JSONObject(); obj.put("swlat",swlat); obj.put("swlng",swlng); obj.put("nelat",nelat); obj.put("nelng",nelng); out.print(obj); out.flush(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } public void init() throws ServletException { // Put your code here } }
?web.xml:
?
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>AjaxMap</servlet-name> <servlet-class>com.wujay.AjaxMap</servlet-class> </servlet> <servlet-mapping> <servlet-name>AjaxMap</servlet-name> <url-pattern>/AjaxMap</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
?我把MyEclipse工程作为附件有需要的可以看看。
?
The End
?
?
?