Event after modifying polygon in Google Maps API v3 - javascript

I made a mapping application that uses the drawing manager (and implements selectable shapes). The program works as follows: when finishing drawing the polygon after clicking a button a path, is mapped on the polygon.
When the polygon is edited after this process I want the mapping function to be called again. However I can't get this part working:
I tried using following code, but I always get an error because no shape is selected yet when this listener is added. What can I do?
google.maps.event.addListener(selectedShape, 'set_at', function() {
console.log("test");
});
google.maps.event.addListener(selectedShape, 'insert_at', function() {
console.log("test");
});
Important pieces of code:
function showDrawingManager(){
var managerOptions = {
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.POLYLINE, google.maps.drawing.OverlayType.POLYGON]
},
markerOptions: {
editable: true,
icon: '/largeTDGreenIcons/blank.png'
},
polygonOptions: {
fillColor: "#1E90FF",
strokeColor: "#1E90FF",
},
polylineOptions: {
strokeColor: "#FF273A"
}
}
var drawingManager = new google.maps.drawing.DrawingManager(managerOptions);
drawingManager.setMap(map);
return drawingManager;
}
function clearSelection() {
if (selectedShape) {
console.log("clearSelection");
selectedShape.setEditable(false);
selectedShape = null;
numberOfShapes--;
}
}
function setSelection(shape) {
console.log("setSelection");
clearSelection();
selectedShape = shape;
shape.setEditable(true);
numberOfShapes++;
//getInformation(shape);
}
function initialize(){
//....
var drawingManager = showDrawingManager();
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type != google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function() {
setSelection(newShape);
});
setSelection(newShape);
}
});

I solved it by calling .getPath() and putting the listener inside the listener which is called every time a shape is clicked. I think the Google API documentation is not very clear on how to use the set_at so it may be useful for other people too.
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function() {
google.maps.event.addListener(newShape.getPath(), 'set_at', function() {
console.log("test");
});
google.maps.event.addListener(newShape.getPath(), 'insert_at', function() {
console.log("test");
});
setSelection(newShape);
});

google.maps.event.addListener(yourPolygon.getPath(), 'insert_at', function(index, obj) {
//polygon object: yourPolygon
});
google.maps.event.addListener(yourPolygon.getPath(), 'set_at', function(index, obj) {
//polygon object: yourPolygon
});
The above code is working for me. Where set_at is fired when we modify a polygon area from a highlighted dot (edges) and insert_at is fired when we drag point that is between highlighted edges.
I used them in the polygoncomplete event and after loading a polygon from the database. It is working fine for them.

To avoid the problems mentioned with set_at and dragging, I added the following, which disables event broadcasting for set_at when the drawing is being dragged. I created a class that extends the polygon class, and added this method:
ExtDrawingPolygon.prototype.enableCoordinatesChangedEvent = function(){
var me = this,
superClass = me.superClass,
isBeingDragged = false,
triggerCoordinatesChanged = function(){
//broadcast normalized event
google.maps.event.trigger(superClass, 'coordinates_changed');
};
// If the overlay is being dragged, set_at gets called repeatedly,
// so either we can debounce that or ignore while dragging,
// ignoring is more efficient.
google.maps.event.addListener(superClass, 'dragstart', function(){
isBeingDragged = true;
});
// If the overlay is dragged
google.maps.event.addListener(superClass, 'dragend', function(){
triggerCoordinatesChanged();
isBeingDragged = false;
});
// Or vertices are added to any of the possible paths, or deleted
var paths = superClass.getPaths();
paths.forEach(function(path, i){
google.maps.event.addListener(path, "insert_at", function(){
triggerCoordinatesChanged();
});
google.maps.event.addListener(path, "set_at", function(){
if(!isBeingDragged){
triggerCoordinatesChanged();
}
});
google.maps.event.addListener(path, "remove_at", function(){
triggerCoordinatesChanged();
});
});
};
It added a "coordinates_changed" event to the polygon itself, so other code can just listen for a nice, single, simplified event.

Starting from chrismarx's answer, below is an example of using a new event in TypeScript. I have done a small change of removing superclass and changing references to "me", because there was a problem with undefined reference.
At the top of your file or global configuration file, etc., use:
declare global {
module google.maps {
interface Polygon {
enableCoordinatesChangedEvent();
}
}
}
Then define extension:
google.maps.Polygon.prototype.enableCoordinatesChangedEvent = function () {
var me = this,
isBeingDragged = false,
triggerCoordinatesChanged = function () {
// Broadcast normalized event
google.maps.event.trigger(me, 'coordinates_changed');
};
// If the overlay is being dragged, set_at gets called repeatedly,
// so either we can debounce that or igore while dragging,
// ignoring is more efficient
google.maps.event.addListener(me, 'dragstart', function () {
isBeingDragged = true;
});
// If the overlay is dragged
google.maps.event.addListener(me, 'dragend', function () {
triggerCoordinatesChanged();
isBeingDragged = false;
});
// Or vertices are added to any of the possible paths, or deleted
var paths = me.getPaths();
paths.forEach(function (path, i) {
google.maps.event.addListener(path, "insert_at", function () {
triggerCoordinatesChanged();
});
google.maps.event.addListener(path, "set_at", function () {
if (!isBeingDragged) {
triggerCoordinatesChanged();
}
});
google.maps.event.addListener(path, "remove_at", function () {
triggerCoordinatesChanged();
});
});
};
Finally call extension and add listener:
google.maps.event.addListener(drawingManager, 'overlaycomplete', function (event) {
event.overlay.enableCoordinatesChangedEvent();
google.maps.event.addListener(event.overlay, 'coordinates_changed', function (index, obj) {
// Polygon object: yourPolygon
console.log('coordinates_changed');
});
});

Starting from Thomas' answer, here is an implementation that enables edits to overlays created with DrawingManager, as well as to Features added from GeoJSON.
The main struggle for me was using the google.maps-prefixed overlay types created by DrawingManager alongside similarly named google.maps.Data Feature types created by addFromGeoJson(). Ultimately I ignored the built-in Data object in favor storing everything as a re-created overlay, setting edit event listeners, and then calling setMap() on them individually as they were drawn. The originally drawn overlays and loaded features are discarded.
The process looks something like this:
Initialize the map.
Add an addfeature event listener to detect whenever a feature is added. This will get fired during addGeoJson() for each Feature, getting its corresponding overlay type and geometry and passing them to a utility function addFeature() to create the overlay.
Load any GeoJSON. This will fire the event listener above for every object loaded in.
Initialize the DrawingManager.
Add {overlay}complete event listeners for each type of overlay (polygon, polyline, and marker). When fired, these events first determine if the overlay is valid (e.g. polygons have >= 3 vertices) and then call addFeature(), passing in the overlay type and geometry.
When called, addFeature() re-creates the overlay and sets all applicable event listeners. Finally, the overlay is stored in the array and displayed on the map.
// GeoJSON containing previously stored data (optional)
var imported = {
type: "FeatureCollection",
features: [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-73.985603, 40.748429
],
},
properties: {
activity: "Entry",
}
}, ]
};
// this will fill with map data as you import it from geojson or draw
var features = {
polygons: [],
lines: [],
markers: []
};
// set default drawing styles
var styles = {
polygon: {
fillColor: '#00ff80',
fillOpacity: 0.3,
strokeColor: '#008840',
strokeWeight: 1,
clickable: true,
editable: true,
zIndex: 1
},
polyline: {
strokeColor: '#ffff00',
strokeWeight: 3,
clickable: true,
editable: true,
zIndex: 2
},
marker: {
clickable: true,
draggable: true,
zIndex: 3
}
}
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 40.748429,
lng: -73.985603
},
zoom: 18,
noClear: true,
mapTypeId: 'satellite',
navigationControl: true,
mapTypeControl: false,
streetViewControl: false,
tilt: 0
});
// add this listener BEFORE loading from GeoJSON
map.data.addListener('addfeature', featureAdded);
// load map features from geojson
map.data.addGeoJson(imported);
// initialize drawing tools
var drawingManager = new google.maps.drawing.DrawingManager({
// uncomment below line to set default drawing mode
// drawingMode: 'marker',
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: ['polygon', 'polyline', 'marker']
},
polygonOptions: styles.polygon,
polylineOptions: styles.polyline,
markerOptions: styles.marker
});
drawingManager.setMap(map);
// for each drawing mode, set a listener for end of drawing
drawingManager.addListener('polygoncomplete', function(polygon) {
// delete drawing if doesn't have enough points
if (polygon.getPath().getLength() < 3) {
alert('Polygons must have 3 or more points.');
polygon.getPath().clear();
}
// otherwise create new feature and delete drawing
else {
addFeature('Polygon', polygon.getPath());
polygon.setMap(null);
}
});
drawingManager.addListener('polylinecomplete', function(line) {
// delete drawing if doesn't have enough points
if (line.getPath().getLength() < 2) {
alert('Lines must have 2 or more points.');
line.getPath().clear();
}
// otherwise create new feature and delete drawing
else {
addFeature('Polyline', line.getPath());
line.setMap(null);
}
});
drawingManager.addListener('markercomplete', function(marker) {
// point geometries have only one point by definition,
// so create new feature and delete drawing
addFeature('Point', marker.getPosition());
marker.setMap(null);
updateGeoJSON();
});
}
// this function gets called when GeoJSON gets loaded
function featureAdded(e) {
switch (e.feature.getGeometry().getType()) {
case 'Polygon':
addFeature('Polygon', e.feature.getGeometry().getAt(0).getArray());
break;
case 'LineString':
addFeature('Polyline', e.feature.getGeometry().getArray());
break;
case 'Point':
addFeature('Point', e.feature.getGeometry().get());
}
map.data.remove(e.feature);
}
function addFeature(type, path) {
switch (type) {
case 'Polygon':
var polygon = new google.maps.Polygon(styles.polygon);
polygon.setPath(path);
// listeners for detecting geometry changes
polygon.getPath().addListener('insert_at', someFunction)
polygon.getPath().addListener('set_at', someFunction);
polygon.getPath().addListener('remove_at', someFunction);
polygon.getPath().addListener('dragend', someFunction);
// delete vertex using right click
polygon.addListener('rightclick', function(e) {
if (e.vertex == undefined) return;
if (polygon.getPath().getLength() == 3) {
polygon.setMap(null);
features.polygons = features.polygons.filter(isValid);
} else {
polygon.getPath().removeAt(e.vertex);
outputAsGeoJSON();
}
});
// add it to our list of features
features.polygons.push(polygon);
// and display it on the map
polygon.setMap(map);
break;
case 'Polyline':
var line = new google.maps.Polyline(styles.polyline);
line.setPath(path);
line.getPath().addListener('insert_at', someOtherFunction);
line.getPath().addListener('set_at', someOtherFunction);
line.getPath().addListener('remove_at', someOtherFunction);
line.getPath().addListener('dragend', someOtherFunction);
// allow right-click vertex deletion
line.addListener('rightclick', function(e) {
if (e.vertex == undefined) return;
if (line.getPath().getLength() == 2) {
line.setMap(null);
features.lines = features.lines.filter(isValid);
} else {
line.getPath().removeAt(e.vertex);
outputAsGeoJSON();
}
});
// add it to our list of features
features.lines.push(line);
// and display it on the map
line.setMap(map);
break;
case 'Point':
var marker = new google.maps.Marker(styles.marker);
marker.setPosition(path);
// make a splashy entrance
marker.setAnimation(google.maps.Animation.DROP);
// detect modifications
marker.addListener('drag', function(e) {
// unnecessary bouncing just to throw you off
marker.setAnimation(google.maps.Animation.BOUNCE);
});
marker.addListener('dragend', function(e) {
// make the bouncing stop
marker.setAnimation(null);
})
// allow right-click deletion
marker.addListener('rightclick', function(e) {
marker.setMap(null);
features.markers = features.markers.filter(isValid);
outputAsGeoJSON();
});
// add it to our list of features
features.markers.push(marker);
// and display it on the map
marker.setMap(map);
break;
}
outputAsGeoJSON();
}
function someFunction() {
// do stuff
}
function someOtherFunction() {
// do other stuff
}
// utility function for reuse any time someone right clicks
function isValid(f) {
return f.getMap() != null;
}
function outputAsGeoJSON() {
// we're only using the Data type here because it can export as GeoJSON
var data = new google.maps.Data;
// add all the polygons in our list of features
features.polygons.forEach(function(polygon, i) {
data.add({
geometry: new google.maps.Data.Polygon([polygon.getPath().getArray()]),
properties: {
description: 'I am a polygon'
}
});
});
// and add all the lines
features.lines.forEach(function(line, i) {
data.add({
geometry: new google.maps.Data.LineString(line.getPath().getArray()),
properties: {
description: 'I am a line'
}
});
});
// and finally any markers
features.markers.forEach(function(marker, i) {
data.add({
geometry: new google.maps.Data.Point(marker.getPosition()),
properties: {
description: 'I am a marker'
}
});
});
// GeoJSONify it
data.toGeoJson(function(json) {
document.getElementById('geojson').value = JSON.stringify(json);
});
}
https://jsfiddle.net/pqdu05s9/1/

Related

ESRI leaflet map, reset style not working

I am working on my first leaflet map and am running into an issue when trying to reset the style onMouseOut. it correctly changes style on mouse over but on mouse out, i keep getting: Object doesn't support property or method 'resetStyle'
This is what i have and what I have tried:
var MAP_ID = 'DISTRICT_MAP';
var map = L.map(MAP_ID).setView([37.71, -99.88], 4);
function showMap() {
var layerConfig = {
....
onEachFeature: onEachFeature,
style: style
};
var districtLayer;
//Add base map layer
L.esri.basemapLayer('Gray').addTo(map);
//Add the District layer
districtLayer = L.esri.featureLayer(layerConfig);
map.addLayer(districtLayer);
}
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7,
});
if (!L.Browser.ie && !L.Browser.opera12 && L.Browser.edge) {
layer.bringToFront();
}
}
// Can't get this to work!
function resetHighlight(e) {
//L.esri.featureLayer.resetStyle(e.target);
//e.target.resetStyle(e.target);
//e.layer.resetStyle();
}
function onEachFeature(feature, layer) {
layer.on("mouseover", function (e) {
highlightFeature(e);
});
layer.on("mouseout", function (e) {
if (e.target && e.target.feature && e.target.feature.properties) {
resetHighlight(e);
}
});
layer.on("click", function (e) {
....
}
});
}
function style(feature, layer) {
...
}
as per the API reference, that is a method on FeatureLayer itself, and expects you to pass the id of a specific feature.
// because the individual feature is GeoJSON, it has an id, along with properties and geometry
districtLayer.resetStyle(e.layer.feature.id);

How to assign unique IDs to drawn GeoJson features and then remove them based on their ID?

I'm trying to assign a unique ID to each feature that gets drawn on this Google Map, and then use the rightclick event to remove the feature that gets clicked on. Currently all features get removed, which is a problem.
Once the feature is added to the collection, I try to assign the unique ID:
var uniqueID = function() {
return ++currentID;
}
dataLayer.addListener('addfeature', savePolygon, function(event) {
event.feature.setProperty('featureID', uniqueID);
});
Then on rightclick event, I want to remove the feature that gets clicked on. I assumed you would need to have unique IDs for this step, hence the prior step.
dataLayer.addListener('rightclick', function() {
dataLayer.forEach(function(feature) {
dataLayer.remove(feature);
localStorage.removeItem('geoData');
});
});
Full code below.
JS:
var map;
var currentID = 0;
var uniqueID = function() {
return ++currentID;
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 4,
// only show roadmap type of map, and disable ability to switch to other type
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
});
map.data.setControls(['Polygon']);
map.data.setStyle({
editable: true,
draggable: true
});
bindDataLayerListeners(map.data);
//load saved data
loadPolygons(map);
}
// Apply listeners to refresh the GeoJson display on a given data layer.
function bindDataLayerListeners(dataLayer) {
dataLayer.addListener('addfeature', savePolygon, function(event) {
event.feature.setProperty('featureID', uniqueID);
});
dataLayer.addListener('rightclick', function() {
dataLayer.forEach(function(feature) {
dataLayer.remove(feature);
localStorage.removeItem('geoData');
});
});
dataLayer.addListener('setgeometry', savePolygon);
}
function loadPolygons(map) {
var data = JSON.parse(localStorage.getItem('geoData'));
map.data.forEach(function(f) {
map.data.remove(f);
});
map.data.addGeoJson(data)
}
function savePolygon() {
map.data.toGeoJson(function(json) {
localStorage.setItem('geoData', JSON.stringify(json));
});
}
initMap();
Original source: I built this example from a JSFiddle found in this thread.
your addfeature listener was wrong, as addListener takes only a single callback function, so you need to call e.feature.setProperty then savePolygon inside a single anonymous callback function
Note, you had event.feature.setProperty('featureID', uniqueID); - it needs to be event.feature.setProperty('featureID', uniqueID());
dataLayer.addListener('addfeature', function(event) {
event.feature.setProperty('featureID', uniqueID());
savePolygon(event);
});
Then, in the rightclick lsitener, you can simply get the geoData - filter out the clicked item, save the geoData and then dataLayer.remove(e.feature);
dataLayer.addListener('rightclick', function(e) {
var data = JSON.parse(localStorage.getItem('geoData'));
data.features = data.features.filter(function(feature) {
return feature.properties.featureID !== e.feature.getProperty('featureID');
});
localStorage.setItem('geoData', JSON.stringify(data));
dataLayer.remove(e.feature);
});
working fiddle

Manually close layer control window (javascript)

I recently started programing in javascript.
I have added a layer control window to my map. It's open by default (This works.). Now I want to add a close button to the layer control window. Is that possible?
This my code:
$ (document).ready(function init(){
// initiate leaflet map
var map = new L.Map('cartodb-map', {
center: [51,9],
zoom: 4,
minZoom:3,
maxZoom: 16,
});
//load basemap
var OSM= new L.tileLayer('http://a{s}.acetate.geoiq.com/tiles/acetate-hillshading/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap'}).addTo(map);
//load data from CartoDB
var layerUrl= 'http://intermodalmap.cartodb.com/api/v2/viz/0931f4e4-76f8-11e4-0e9d821ea90d/viz.json';
//load satellit map
var Esri_WorldImagery = new L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' });
var baseLayers = { "Standardkarte": OSM,
"Satellitenkarte": Esri_WorldImagery };
//create map
cartodb.createLayer(map, layerUrl,
{https: true,
legends: true,
cartodb_logo:false,
layerIndex: 1
})
.addTo(map)
.on('done', function() {
});
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
var control = new L.Control.Custom(baseLayers, {"Alle Terminals":layerUrl}, {collapsed:false}).addTo(map);
// create a fullscreen button and add it to the map
L.control.fullscreen({
position: 'topleft', // change the position of the button can be topleft, topright, bottomright or bottomleft, defaut topleft
title: 'Open fullscreen', // change the title of the button, default Full Screen
titleCancel: 'Exit fullscreen mode', // change the title of the button when fullscreen is on, default Exit Full Screen
content: null, // change the content of the button, can be HTML, default null
forceSeparateButton: true
}).addTo(map);
// events are fired when entering or exiting fullscreen.
map.on('enterFullscreen', function(){
console.log('entered fullscreen');
});
map.on('exitFullscreen', function(){
console.log('exited fullscreen');
});
//add scale
L.control.scale({metric:"m", position:"bottomright", imperial:false}).addTo(map);
//end of function init
}
)
You can extend L.Control.Layers and add elements to it's container, attach eventhandlers, whatever you want. Something like this:
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
Example: http://plnkr.co/edit/Je7c0m?p=preview
cartodb.createLayer(map, layerUrl, {
layerIndex: 1
}).addTo(map)
.on('done', function(layer) {
L.control.layers(baseLayers,
{data:layer},
{collapsed:false}
).addTo(map);
document.getElementById('closeBtn').addEventListener('click', function() {
layer.setAttribute('style', 'display: none;').hide();
});
});
// and more shortly if jquery exists
$('#closeBtn').click(function() {
layer.hide();
});

Delete a DrawingManager shape when drawing a new one

I created a custom toggle to init the DrawingManager, and I'm able to delete the current shape (if there is one) when I initialise it using currentShape.setMap(null).
But how to delete a shape created with the DrawingManager at the precise moment the user starts do draw a new one?
As far as I know there's no "drawingstart" event (not in their documentation), for example, that could fire at the moment when the user starts drawing a shape.
I tried using this...
google.maps.event.addListener(map, 'dragstart', function(e) {
if (drawingManager.getDrawingMode() == "circle"){
currentShape.setMap(null);
}
});
...and also using the 'click' event, but those events don't fire when drawingManager.getDrawingMode() == "circle".
function initMap(){
map = new google.maps.Map(mapCanvas, mapOptions);
$toggleDrawing.on('click', function(){
toggleDrawing();
});
}
function toggleDrawing(){
if (!isDrawing){
if (!selectedArea){
// enable drawing mode
isDrawing = true;
$toggleDrawing.addClass('active');
initDrawing();
}else{
// delete selected area
deleteSelectedArea();
}
}else{
// disable drawing mode after drawing a shape
isDrawing = false;
$toggleDrawing.removeClass('active');
drawingManager.setDrawingMode(null);
}
}
function initDrawing(){
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.CIRCLE,
drawingControl: false
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
selectedArea = e.overlay;
toggleDrawing(false); // will set to false
});
// 'click' or 'dragstart' event are not fired if `drawingManager.getDrawingMode() == "circle"` (or any other shape)
// google.maps.event.addListener(map, 'click', function(e) {
// if (drawingManager.getDrawingMode() == "circle"){
// selectedArea.setMap(null);
// }
// });
// google.maps.event.addListener(map, 'dragstart', function(e) {
// if (drawingManager.getDrawingMode() == "circle"){
// selectedArea.setMap(null);
// }
// });
}
function deleteSelectedArea() {
if (selectedArea) {
selectedArea.setMap(null);
selectedArea = null;
}
}
Too easy. Attach event to the map-canvas instead of map:
// If it's drawing mode, delete the selected area (if there is one)
$('#map-canvas').on('click', function() {
if (drawingManager.getDrawingMode() == "circle"){
deleteSelectedArea();
}
});
Nice tips here.

label for circle marker in leaflet

I am able to add label to circlemarker like this
L.circleMarker(points[i],{title: 'unselected'}).bindLabel('Destination').addTo(map);
This adds label which appears on mouse hover on circle marker.
But I want to add static label which will appear regardless of mouse is on that circle marker or not.
I am referring this demo http://leaflet.github.com/Leaflet.label/ for adding static label to circle marker but some how I am not able to do it.
It is working fine with markers but with circle Markers static label is not working.
Also is there any other method to add label on circle marker ?
L.CircleMarker extended from L.Path not L.Marker, so if you compare https://github.com/Leaflet/Leaflet.label/blob/master/src/Path.Label.js and https://github.com/Leaflet/Leaflet.label/blob/master/src/Marker.Label.js you can find that Path doesn't have any options and this logic you must implement yourself. For example:
L.CircleMarker.include({
bindLabel: function (content, options) {
if (!this._label || this._label.options !== options) {
this._label = new L.Label(options, this);
}
this._label.setContent(content);
this._labelNoHide = options && options.noHide;
if (!this._showLabelAdded) {
if (this._labelNoHide) {
this
.on('remove', this.hideLabel, this)
.on('move', this._moveLabel, this);
this._showLabel({latlng: this.getLatLng()});
} else {
this
.on('mouseover', this._showLabel, this)
.on('mousemove', this._moveLabel, this)
.on('mouseout remove', this._hideLabel, this);
if (L.Browser.touch) {
this.on('click', this._showLabel, this);
}
}
this._showLabelAdded = true;
}
return this;
},
unbindLabel: function () {
if (this._label) {
this._hideLabel();
this._label = null;
this._showLabelAdded = false;
if (this._labelNoHide) {
this
.off('remove', this._hideLabel, this)
.off('move', this._moveLabel, this);
} else {
this
.off('mouseover', this._showLabel, this)
.off('mousemove', this._moveLabel, this)
.off('mouseout remove', this._hideLabel, this);
}
}
return this;
}
});
L.circleMarker([53.902257, 27.541640] ,{title: 'unselected'}).addTo(map).bindLabel('Destination', { noHide: true });
Just wanted to add an update or correction to tbicr's great response (not sure if the API updated after his response).
You can do this like so:
// First add your GeoJSON layer
geojson = L.geoJson(myGeoJson,{
onEachFeature: onEachFeature
}).addTo(map);
// onEachFeature is called every time a polygon is added
var polys = [];
function onEachFeature(layer){
polys.push(layer); // Push the polygons into an array you can call later
}
// Now trigger them after they've been added
$('a').click(function(){
polys[0].fire('click') // clicks on the first polygon
polys[1].fire('click') // clicks on the second polygon
});

Categories