简体   繁体   English

在Google Maps API v3中使用单独的删除按钮绘制圆形/多边形

[英]Drawing Circles / Polygons With Individual Delete Buttons in Google Maps API v3

This is to help people who have been trying to implement this or have been looking for this solution like I did for quite some time. 这是为了帮助那些尝试实施此解决方案或像我很长时间以来一直在寻找此解决方案的人们。 Not being successful at finding an existing solution, I finally decided to do it. 未能成功找到现有解决方案,我最终决定这样做。

How to add a Delete Button or a X mark to a drawn shape (circle / polygon) so that individual shapes can be deleted using this button? 如何在绘制的形状(圆形/多边形)上添加“删除按钮”或X标记,以便可以使用此按钮删除单个形状?

This is the Github Link to view the library and also a complete working example. 这是查看库的Github链接 ,也是完整的工作示例。

On drawing a circle, a delete button (X mark) would be placed at 45 degrees (north-east) on the circle circumference. 在绘制圆时,将在圆圆周上以45度(东北)放置删除按钮(X标记)。 For polygons, since they can be unpredictable, I am placing the delete button(X mark) next to the polygon's first vertex. 对于多边形,由于它们可能不可预测,因此我将删除按钮(X标记)放在多边形的第一个顶点旁边。

You can either delete individual circles/polygons or Clear all shapes drawn. 您可以删除单个圆/多边形或清除所有绘制的形状。

To directly call the library in your HTML file use the following script, 要直接在HTML文件中调用该库,请使用以下脚本,
<script src="https://gist.github.com/loyalvares/c4ba7420b1eb055b309ab48bdcd34219.js"></script>

This is the JSFiddle Link to the same. 这与JSFiddle链接相同。

 /* * Method that is called when Google Maps API is loaded. */ function initMap() { setInitialMapOptions(); map = getMapObject(mapOptions); drawingManager = getDrawingManagerObject(); google.maps.event.addListener(drawingManager, 'overlaycomplete', onOverlayComplete); initializeDeleteOverlayButtonLibrary(); } // Get Map Geo Center Denver, USA Coordinates var center = {lat: 39.810866, lng: -104.990347}; var map, drawingManager, mapOptions = {}; var listenerFiltersApplied = false; var overlays = {}; var circleOptions = { fillColor: "#e20000", fillOpacity: 0, strokeColor: "#e20000", strokeWeight: 4, strokeOpacity: 1, clickable: false, editable: true, suppressUndo: true, zIndex: 999 }; var polygonOptions = { editable: true, fillColor: "#e20000", fillOpacity: 0, strokeColor: "#e20000", strokeWeight: 4, strokeOpacity: 1, suppressUndo: true, zIndex: 999 }; function setInitialMapOptions() { mapOptions = { zoom: 4, center: center, styles: [ {"featureType":"road", elementType:"geometry", stylers: [{visibility:"off"}]}, //turns off roads geometry {"featureType":"road", elementType:"labels", stylers: [{visibility:"off"}]}, //turns off roads labels {"featureType":"poi", elementType:"labels", stylers: [{visibility:"off"}]}, //turns off points of interest lines {"featureType":"poi", elementType:"geometry", stylers: [{visibility:"off"}]}, //turns off points of interest geometry {"featureType":"transit", elementType:"labels", stylers: [{visibility:"off"}]}, //turns off transit lines labels {"featureType":"transit", elementType:"geometry", stylers: [{visibility:"off"}]}, //turns off transit lines geometry {"featureType":"administrative.land_parcel", elementType:"labels", stylers: [{visibility:"off"}]}, //turns off administrative land parcel labels {"featureType":"administrative.land_parcel", elementType:"geometry", stylers: [{visibility:"off"}]}, //turns off administrative land parcel geometry {"featureType":"water", elementType:"geometry", stylers: [{color: '#d1e1ff'}]}, //sets water color to a very light blue {"featureType":"landscape", elementType:"geometry", stylers: [{color: '#fffffa'}]}, //sets landscape color to a light white color ], mapTypeControl: false, panControl: true, panControlOptions: { position: google.maps.ControlPosition.RIGHT_CENTER }, streetViewControl: false, scaleControl: false, zoomControl: true, zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL, position: google.maps.ControlPosition.RIGHT_BOTTOM }, minZoom: 2 }; } function getMapObject(mapOptions) { var map = new google.maps.Map(document.getElementById('map'), mapOptions); return map; } function getDrawingManagerObject(drawingManagerOptions) { var drawingManager = new google.maps.drawing.DrawingManager({ drawingMode: null, drawingControl: true, drawingControlOptions: { position: google.maps.ControlPosition.TOP_CENTER, drawingModes: [ google.maps.drawing.OverlayType.CIRCLE, google.maps.drawing.OverlayType.POLYGON ] }, circleOptions: circleOptions, polygonOptions: polygonOptions }); drawingManager.setMap(map); return drawingManager; } /* -- Overlay Functions Begin Here -- */ function onOverlayComplete(shape) { addDeleteButtonToOverlay(shape); addOverlayListeners(shape); if(listenerFiltersApplied) { listenerFiltersApplied = false; } } function addOverlayListeners(shape) { // Filters already applied. if(listenerFiltersApplied) { return; } if (shape.type == google.maps.drawing.OverlayType.POLYGON) { setBoundsChangedListener(shape); } if (shape.type == google.maps.drawing.OverlayType.CIRCLE) { setCenterChangedListener(shape); setRadiusChangedListener(shape); } } function setBoundsChangedListener(shape) { // Add listeners for each path of the polygon. shape.overlay.getPaths().forEach(function(path, index){ // New point google.maps.event.addListener(path, 'insert_at', function(){ listenerFiltersApplied = true; onOverlayComplete(shape); }); // Point was removed google.maps.event.addListener(path, 'remove_at', function(){ listenerFiltersApplied = true; onOverlayComplete(shape); }); // Point was moved google.maps.event.addListener(path, 'set_at', function(){ listenerFiltersApplied = true; onOverlayComplete(shape); }); }); } function setCenterChangedListener(shape) { google.maps.event.addListener(shape.overlay, 'center_changed', function() { listenerFiltersApplied = true; onOverlayComplete(shape); }); } function setRadiusChangedListener(shape) { google.maps.event.addListener(shape.overlay, 'radius_changed', function() { listenerFiltersApplied = true; onOverlayComplete(shape); }); } function addDeleteButtonToOverlay(shape) { var deleteOverlayButton = new DeleteOverlayButton(); if(("deleteButton" in shape) && (shape.deleteButton != null)) { shape.deleteButton.div.remove(); shape.deleteButton = deleteOverlayButton; } else { shape.deleteButton = deleteOverlayButton; } if(shape.type == google.maps.drawing.OverlayType.CIRCLE) { var radiusInKms = convertDistance(Math.round(shape.overlay.getRadius()), "metres", "kms"); var circleCenter = new google.maps.LatLng(shape.overlay.getCenter().lat(), shape.overlay.getCenter().lng()); var deleteOverlayButtonPosition = circleCenter.destinationPoint(30, radiusInKms); deleteOverlayButton.open(map, deleteOverlayButtonPosition, shape); } else if (shape.type == google.maps.drawing.OverlayType.POLYGON) { deleteOverlayButton.open(map, shape.overlay.getPath().getArray()[0], shape); } if (!('uid' in shape)) { shape.uid = Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36); } overlays[shape.uid] = shape; } function clearAllOverlays() { for(var shapeId in overlays) { if(overlays.hasOwnProperty(shapeId)) { var shape = overlays[shapeId]; if(("deleteButton" in shape) && (shape.deleteButton != null)) { shape.deleteButton.div.remove(); } shape.overlay.setMap(null); } } overlays = {}; } /* * Add any code that needs to be run or cleaned up in this method. * This method is called in DeleteOverlayButton.removeShape(). */ function callOnDelete(shape) { if(shape['uid'] in overlays) { delete overlays[shape['uid']]; } } /* -- Overlay Functions End Here -- */ function convertDistance(distanceValue, actualDistanceUnit, expectedDistanceUnit) { var distanceInKms = 0; switch(actualDistanceUnit) { case "miles": distanceInKms = distanceValue/0.62137; break; case "kms": distanceInKms = distanceValue; break; case "metres": distanceInKms = distanceValue/1000; break; default: distanceInKms = undefined; } switch(expectedDistanceUnit) { case "miles": return distanceInKms * 0.62137; case "kms": return distanceInKms; case "metres": return distanceInKms * 1000; default: return undefined; } } /* ***** Custom Library for Delete Overlay Button (Start) ***** */ /** * A HTML Button that lets a user delete a component. * @constructor * @author: Loy Alvares */ function DeleteOverlayButton() { this.div = document.createElement('div'); this.div.id = 'deleteOverlayButton'; this.div.className = 'deleteOverlayButton'; this.div.title = 'Delete'; this.div.innerHTML = '<span id="x">X</span>'; var button = this; google.maps.event.addDomListener(this.div, 'click', function() { button.removeShape(); button.div.remove(); }); } function initializeDeleteOverlayButtonLibrary() { /* This needs to be initialized by initMap() */ DeleteOverlayButton.prototype = new google.maps.OverlayView(); /** * Add component to map. */ DeleteOverlayButton.prototype.onAdd = function() { var deleteOverlayButton = this; var map = this.getMap(); this.getPanes().floatPane.appendChild(this.div); }; /** * Clear data. */ DeleteOverlayButton.prototype.onRemove = function() { google.maps.event.removeListener(this.divListener_); this.div.parentNode.removeChild(this.div); // Clear data this.set('position'); this.set('overlay'); }; /** * Deletes an overlay. */ DeleteOverlayButton.prototype.close = function() { this.setMap(null); }; /** * Displays the Button at the position(in degrees) on the circle's circumference. */ DeleteOverlayButton.prototype.draw = function() { var position = this.get('position'); var projection = this.getProjection(); if (!position || !projection) { return; } var point = projection.fromLatLngToDivPixel(position); this.div.style.top = point.y + 'px'; this.div.style.left = point.x + 'px'; if(this.get('overlay').type == google.maps.drawing.OverlayType.POLYGON) { this.div.style.marginTop = '-16px'; this.div.style.marginLeft = '0px'; } }; /** * Displays the Button at the position(in degrees) on the circle's circumference. */ DeleteOverlayButton.prototype.open = function(map, deleteOverlayButtonPosition, overlay) { this.set('position', deleteOverlayButtonPosition); this.set('overlay', overlay); this.setMap(map); this.draw(); }; /** * Deletes the shape it is associated with. */ DeleteOverlayButton.prototype.removeShape = function() { var position = this.get('position'); var shape = this.get('overlay'); if (shape != null) { shape.overlay.setMap(null); /* Add any cleanup code or any other events in the below method. */ callOnDelete(shape); return; } this.close(); }; Number.prototype.toRadians = function() { return this * Math.PI / 180; } Number.prototype.toDegrees = function() { return this * 180 / Math.PI; } /* Based the on the Latitude/Longitude spherical geodesy formulae & scripts at http://www.movable-type.co.uk/scripts/latlong.html (c) Chris Veness 2002-2010 */ google.maps.LatLng.prototype.destinationPoint = function(bearing, distance) { distance = distance / 6371; bearing = bearing.toRadians(); var latitude1 = this.lat().toRadians(), longitude1 = this.lng().toRadians(); var latitude2 = Math.asin(Math.sin(latitude1) * Math.cos(distance) + Math.cos(latitude1) * Math.sin(distance) * Math.cos(bearing)); var longitude2 = longitude1 + Math.atan2(Math.sin(bearing) * Math.sin(distance) * Math.cos(latitude1), Math.cos(distance) - Math.sin(latitude1) * Math.sin(latitude2)); if (isNaN(latitude2) || isNaN(longitude2)) return null; return new google.maps.LatLng(latitude2.toDegrees(), longitude2.toDegrees()); } } /* ***** Custom Library for Delete Overlay Button (End) ***** */ 
 /* Always set the map height explicitly to define the size of the div element that contains the map. */ .map { height: 100%; } /* Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } /* CSS for the Delete Button. */ .deleteOverlayButton { background: #dee0df; color: #000; /* font-family: 'Helvetica', 'Arial', sans-serif; */ font-size: 11.4px; font-weight: bold; text-align: center; width: 14px; height: 15px; border-radius: 8px; box-shadow: 1px 0px -1px rgba(0, 0, 0, .3); position: absolute; padding: 0px 0px 0px 0px; margin-top: 7px; margin-left: 8px; border: 1px solid #999; cursor: pointer; } .deleteOverlayButton:hover { background: #eee; } #clearOverlays { font-family: var(--websiteFont); top: 10%; position: absolute; right: 1%; background: rgb(34,55,65); border-radius: 4px; color: white; border: 1px solid rgb(34,55,65); padding: 2px 6px; cursor: pointer; } 
 <div id="map" class="map"></div> <input id='clearOverlays' onclick="clearAllOverlays();" type=button value="Clear Shapes" /> <link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css" /> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyD7MXQvcn_gskiZeZGhhXekqN1zjUX9fVM&libraries=drawing&callback=initMap" async defer></script> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM