Allow point delete in polygon drawing mode - mapbox

I'm working on a project with Mapbox and I want to customize how I draw the polygon, basically I want to allow point delete on button click and keep in drawing mode.I implemented the behavior, but the point does not get deleted.
I appreciate your help!
var description = "<button id='popup'> Button</button>"
function handlePop(coords) {
var feature = { type: 'Point', coordinates: coords };
draw.delete(feature);
}
let point = 0;
map.on('click', () => {
const coords = draw.getAll().features[0].geometry.coordinates[0];
if (point) {
new mapboxgl.Popup({ closeButton: false })
.setLngLat(coords[point])
.setHTML(description)
.addTo(map);
document.getElementById('popup').addEventListener('click', handlePop(coords[point]));
}
point++;
});

Related

Leaflet current position multiple markers

Hello everyone I have some problems its about the current positionmarker in my leaflet its supposed to update every 3 second and it does but it everytime it puts a new "position" marker on the map and the old one stays how can i fix this?
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: '© Leaflet 2021',
tileSize: 512,
zoomOffset: -1,
id: 'mapbox/streets-v11',
accessToken: '######'
}).addTo(map);
var greenIcon = L.icon({
iconUrl: 'person.png',
iconSize: [35, 35], // size of the icon // the same for the shadow
popupAnchor: [0, -20] // point from which the popup should open relative to the iconAnchor
});
// placeholders for the L.marker and L.circle representing user's current position and accuracy
var current_position, current_accuracy;
function onLocationFound(e) {
var radius = e.accuracy / 2;
var marker;
L.marker(e.latlng, {icon: greenIcon}).addTo(map)
}
// wrap map.locate in a function
function locate() {
map.locate({setView: true, maxZoom: 15});
}
map.on('locationfound', onLocationFound);
// call locate every 3 seconds... forever
setInterval(locate, 3000);
An efficient way to fix this is to keep a reference to the marker you create, so that you can update its position rather than creating a new marker each time you get a location update. The reference needs to be held in a variable that is outside your callback function, but in scope when the callback is created.
For instance, your callback can check whether the marker already exists, and either create it and attach it to the map object for easy re-use, or just update its coordinates if it is already there:
function onLocationFound(e) {
var radius = e.accuracy / 2;
if (map._here_marker) {
// Update the marker if it already exists.
map._here_marker.setLatLng(e.latlng);
} else {
// Create a new marker and add it to the map
map._here_marker = L.marker(e.latlng, {icon: greenIcon}).addTo(map);
}
}
Having this reference will also let you edit the marker from other functions, e.g. to change the icon or popup, hide it from view, etc.
You can do it, for example, in the following way.
Add an ID (customId) to the marker:
const marker = L.marker([lng, lat], {
id: customId
});
And when you add a new marker remove the existing one with the code below:
map.eachLayer(function(layer) {
if (layer.options && layer.options.pane === "markerPane") {
if (layer.options.id !== customId) {
map.removeLayer(layer);
}
}
});

Get all polygon or layer details after polygon draw in leaflet draw

I am trying to get the layer details of the map which are already overlay on the map. When leaflet draw is created I want to get the layer details (Not the polygon coordinates created by leaflet draw plugin) so that I can use them.
I am able to get the coordinates of drawn polygon but that's not what I want.
var draw_layer = new L.FeatureGroup();
mymap.addLayer(draw_layer);
var drawControlFull = new L.Control.Draw({
draw: {
polygon: {
allowIntersection: false, // Restricts shapes to simple polygons
drawError: {
color: '#e1e100', // Color the shape will turn when intersects
message: '<strong>Oh snap!<strong> you can\'t draw that!' // Message that will show when intersect
},
shapeOptions: {
color: '#97009c'
}
},
// disable toolbar item by setting it to false
polyline: false,
circle: false,
rectangle: false,
marker: false,
circlemarker: false
},
edit: {
featureGroup: draw_layer,
remove: true
}
});
mymap.addControl(drawControlFull);
mymap.on(L.Draw.Event.CREATED, function (e) {
var type = e.layerType, layer = e.layer;
if(type === 'polygon'){
var _ajax_cords = [];
var _coords = layer.getLatLngs()[0];
$.each(_coords,function(ind,val){
var _te_co = {x : val.lat, y : val.lng};
_ajax_cords.push(_te_co);
});
}
//if (type === 'polygon') {layer.bindPopup('A popup!');}draw_layer.addLayer(layer);
});
Well I can get the marker detail as I get lot of posts on that but didn't see a post how to get the polygon details.
Any help on this is much appreciable

Leaflet Draw and Leaflet Snap with geojson polygon layers

I'm trying to enable snapping (using Leaflet Snap)in a Leaflet application I'm creating. I'm using Leaflet Draw. Existing layers are read in from a database in geojson. I add these to the guideLayers and I add newly created features there too. It's not working. Has anyone successfully been able to create something like this? That is, been able to create a new polygon and snap to existing polygons in leaflet (geojson layers)? Thanks Dan.
Add geojson to guideLayers code:
function renderLta(_ltas,ltaLayerName) {
L.geoJSON([_ltas.geoJson], {
name:_ltas.id,
areaName:_ltas.localThreatAreaName,
areaDescription:_ltas.localThreatAreaDescription,
style: function (feature) {
return _getLtaStyle(1);
},
onEachFeature: function onEachFeature(feature, layer) {
ltaLayerName.addLayer(layer);
guideLayers.push(layer);
layer.on('click', function(e) {
if(selectedFeature) {
selectedFeature.editing.disable();
// Has there been a change? Does the user need to save?
// get layer again and redraw
drawnItems.removeLayer(selectedFeature);
selectedFeature.addTo(map_lta);
}
selectedFeature = e.target;
e.target.editing.enable();
drawnItems.addLayer(e.target);
});
}
});
ltaLayerName.addTo(map);
Add new layer/data to guideLayers code:
map.on(L.Draw.Event.CREATED, function(event) {
var layer = event.layer;
var content = getPopupContent(layer);
if (content !== null) {
layer.bindPopup(content);
}
drawnItems.addLayer(layer);
guideLayers.push(layer);
});
DrawControl Code:
var drawControl = new L.Control.Draw({
edit: {
featureGroup: drawnItems,
poly : {
allowIntersection : false
}
},
draw: {
polyline: false,
polygon : { showArea: true, allowIntersection : false, guideLayers: guideLayers, snapDistance: 500 },
circle: false,
rectangle: false,
marker: false,
circlemarker: false
}
});
map_lta.addControl(drawControl);
drawControl.setDrawingOptions({
polygon: { guideLayers: guideLayers, snapDistance: 50 },
});
You can use the following library to draw and snap https://www.npmjs.com/package/#geoman-io/leaflet-geoman-free packages
and for more functionalities which are not present in above mentioned package you can use this one especially for polylines
https://www.npmjs.com/package/leaflet-linestring-editor
I gave up on the leaflet draw library and snap, and used leaflet-geoman library instead. Snapping working perfectly.

leaflet routing.control update when marker is moved

I am using leaflet and routing.control to show a route. I have it working fine, but I would like one of the markers to move with the users location using watch.position. But for now I a just trying to move the marker when I click a button. Again this works fine but when the marker moves I would like the route to update automatically. Its possible if you drag the marker so surely its possible when marker is moved in a different way? I can it if I remove the control and add a new one but this flickers too much. Any advice?
The code for the routing.control is
myroute = L.Routing.control({
waypoints: [
L.latLng(window.my_lat, window.my_lng),
L.latLng(window.job_p_lat, window.job_p_lng)
],show: true, units: 'imperial',
router: L.Routing.mapbox('API KEY HERE'),
createMarker: function(i, wp, nWps) {
if (i === 0 || i === nWps + 1) {
return mymarker = L.marker(wp.latLng, {
icon: redIcon
});
} else {
return job_start = L.marker(wp.latLng, {
icon: greenIcon
});
}
}
}).addTo(map);
and the code for moving the marker is
function movemarker() {
var lat = "52.410490";
var lng = "-1.575950";
var newLatLng = new L.LatLng(lat, lng);
mymarker.setLatLng(newLatLng);
// I assume I call something here?
}
Sorted, I did it with this, which removes first point and replaces it with new data
myroutewithout.spliceWaypoints(0, 1, newLatLng);

Google Map Makers Sprite in OSX not displaying

I can't seem to get the my map markers to display when I use an image sprite on the iphone. They appear when I use the standard google map markers on iphone and when viewing the site in the desktop the sprite icons work fine.
Here is the code I use to create the markers, I am using Zepto but JQuery could as easily apply.
$.ajax({
dataType: 'jsonp',
url: myLocations.LocatorUrl,
timeout: 8000,
success: function(data) {
var infoWindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
$.each(data, function(index, item){
var data = item, pincolor,
latLng = new google.maps.LatLng(data.lat, data.lng);
var d = 'http://blah';
var pinImage = new google.maps.MarkerImage(d+"/assets/img/sprite.locator.png",
new google.maps.Size(24, 36),
new google.maps.Point(0,25),
new google.maps.Point(10, 34));
// Creating a marker and putting it on the map
var marker = new google.maps.Marker({
position: latLng,
map: map,
title: data.type,
icon: pinImage
});
bounds.extend(latLng); // Extend the Latlng bound method
var bubbleHtml = '<div class="bubble"><h2>'+item.type+'</h2><p>'+item.address+'</p></div>'; // Custom HTML for the bubble
(function(marker, data) {
// Attaching a click event to the current marker
google.maps.event.addListener(marker, "click", function(e) {
infoWindow.setContent(bubbleHtml);
infoWindow.open(map, marker);
});
markers.push(marker); // Push markers into an array so they can be removed
})(marker, data);
});
map.fitBounds(bounds); // Center based on values added to bounds
}, error: function(x, t, m) {
console.log('errors')
if(t==="timeout") {
alert("got timeout");
} else {
alert(t);
}
}
});
Got it. Turns out the images I was referencing were on localhost, when I swapped this to the actual IP address of my local machine it worked.