How to allow visitors to add new markers in Openlayers or Leaflet - leaflet

I'm working on an open mapping project and am trying to create a map that would enable website visitors to add markers to the map with some info input fields (markers would be visible by all after approved).
I discovered OpenLayers and Leaflet which both seem promising, and spent some time putting together basic maps, but after a lot of searching I've been unable to find anything on allowing visitors to add new markers to maps made with these two tools. Anyone know if this is possible ~~ or if there's another open source tool that would work better for this application? I'm solid in HTML//CSS and know basics of JQUERY - but am not well versed in javascript so if there are more plug-n-play tools thats preferred, but if not I'm willing to do the work to learn...
Thanks!

Yes you can, check out https://openlayers.org/en/latest/examples/draw-features.html to draw the feature(Point/Line/Polygon) on map vector layer
and then you can grab that feature and save it in database and reproduce it later depending upon your business logic.
You can save the drawing from the above example some what like this in javascript:
var features = source.getSource().getFeatures();
To get Point's coordinates :
var lonlat = features[0].getGeometry().getCoordinates();
var longitude = lonlat[0];
var latitude = lonlat[1];
But as ghybs said, you need to do back end work as well.

you need in LEAFLET but this solution is in NUXTjs add this to you code:
#dblclick to you event method and get new lat al lng points to store in database o do something:
<div id="map-wrap" style="height: 100vh">
<no-ssr>
<l-map :zoom="13" :center="[-16.5002, -68.1493]" #dblclick="newMarkerbyClient">
<l-tile-layer
url="https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png"
></l-tile-layer>
<l-marker :lat-lng="[xPosition, yPosition]"></l-marker>
</l-map>
</no-ssr>
</div>
and you script
data() {
return {
xPosition: -16.5002,
yPosition: -68.1493,
}
},
methods: {
newMarkerbyClient(e) {
console.log("x: " + e.latlng.lat + " y:" + e.latlng.lng);
this.xPosition = e.latlng.lat;
this.yPosition = e.latlng.lng;
//xPosition and yPosition are you new point provided by client and you can do anything with this
}
}
Regards from BOLIVIA

Related

Update Popup data in Mapbox GL JS

I'm making a fleet tracker with Mapbox GL JS, it gets the data from a GeoJson and inserts in the map, as the Add live realtime data, I've also integrated the Mapbox store locator example, by now I can update in realtime the sidebar and the points on the map. A modification that I would like to make is not display only one single popup, but a popup for every icon located there. I would like to know how to update this popups, because in the way I'm making it's creating a new popup every movement of the object, but is not closing the previous one. Here is the function that I'm using for the popups
function createPopUp(currentFeature, data) {
var popUps = document.getElementsByClassName('mapboxgl-popup');
//if (popUps[0]) popUps[0].remove();
// mapboxgl.Popup.remove();
if (map.getZoom() > 9) {
var popup = new mapboxgl.Popup({closeOnClick: false})
.setLngLat(currentFeature.geometry.coordinates)
.setHTML('<h3> Aeronave: '+ currentFeature.properties.dev_id + '</h3>' +
'<h4> Curso: ' + currentFeature.properties.curso + 'º<br> Altitude: ' + currentFeature.properties.alt + ' ft<br> Sinal: ' + currentFeature.properties.rssi +'</h4>')
.addTo(map)
.setMaxWidth("fit-content(10px)");
} else{if (popUps[0]) popUps[0].remove()};
}
If I uncomment the popUps[0] line it will only allow 1 popup to be displayed, I've also tried to change dynamically the number between the [] by the number of active tracked devices, it reduced the popup number, but it still repeat some popups of one ID. Also I've tried to change the class name via the .addClasName but it didn't worked.
Thanks
Without seeing how you're calling the createPopUp method in the context of your application, it is difficult to diagnose exactly what is going wrong. I'm not sure why a new popup is being created each time the map moves, so it sounds like you might be calling this method within the Map#on('move') event. That being said, I'm assuming that you're iterating over all of your features and calling the createPopUp method for each in order to initialize all of the popups.
Rather than using an array of DOM nodes generated with var popUps = document.getElementsByClassName('mapboxgl-popup');, I'd recommend specifying a unique and reproducible class name for each feature's popup element when initialized. It looks like each of your features has a dev_id property, so you could do something like:
var popup = new mapboxgl.Popup({closeOnClick: false, className: `mapbox-gl-popup-${dev_id}`})
If you need to change the popup for a particular feature in the future, you can create a helper function to retrieve the relevant DOM node:
function retrievePopUp(feature) {
return document.getElementsByClassName(`mapboxgl-popup-${feature.properties.dev_id}`);
}

Capturing DOM Value using GTM

Total noob here so please bear with me:
I am trying to setup dynamic FB remarketing on a client ecommerce site.The problem is that the site doesn't have a data layer setup for this process so I'm trying to scrape some ecommerce values from the DOM (specifically the product name).
Essentially I am trying to capture the product name from this code string from the order confirmation page:
<h3> <p> **Icebreaker® Pocket Hat - Black/Cargo** </p> </h3>
The "Icebreaker® Pocket Hat - Black Cargo" is what I'm trying to feed into a custom FB pixel as a DOM variable in GTM. I've been experimenting all sorts of things but nothing has really worked so far. I've already captured order value this way so I'm fairly confident this is at least possible.
On the same order confirmation page, there is also this bit of JavaScript with the product name in it should that be of use as well:
<script type="text/javascript"> var gbTracker = new GbTracker('cabelasca', 'Production'); gbTracker.autoSetVisitor(); var visitorId = gbTracker.getVisitorId(); var sessionId = gbTracker.getSessionId(); gbTracker.sendOrderEvent({ cart: { items: [ { productId: '79530', title: '**Icebreaker® Pocket Hat - Black/Cargo**', price: 24.97, quantity: 1 }, ] } }); </script>
I am hoping someone knows how to pass this value using some kind of custom GTM variable. Any nudge towards an answer would be greatly appreciated. Thanks guys.
What I would normally do if I need to get some data from DOM is:
Create DOM element variable
This variable will find all necessary data from DOM. For example in your case variable should be like that:
CSS selector: h3 > p > a
Use this variable in your tags
Then in your tags just use this variable like that: {{Product Title}}

How to generate "highlighted country" maps

How can I generate a map like this using OSM? I want the map to highlight single country and fade others. Also, if the country is small I want to show it on the globe in a small thumbnail.
Oke let’s using JavaScript, because I think there is the biggest variety of libraries. Here I will explain a few approaches creating an interactive webmap.
1) The first approach is using plain svg:
You can download or draw with your vector software of choice the base map as svg. Then you could assign every country polygon a unique ID, and inside JS you can access the SVG with a mouseevent like click or mouseover. All the information of the country could be stored outside JS in a .json (easier) or .xml file. With the ID you getting from the SVG event you can get the fitting information from your .json. Maybe that reinvent the wheel, but it’s highly adjustable. But I think if you only want a static maps its simpler if you are using a more complex library.
2) The second approach is using a library for svg interaction:
The very popular D3.js or Raphael.js
3) The third approach is using a thematic webmapping library based on svg:
Use JQVMAP (former vectormap.js) or the very new austrian project mapmap.js
4) Use a topographic webmapping library
Here you can use the open libraries leaflet.js or openlayers.js. With these, the best approach will be, that you add your countries as a .geojson. Geojson is a very nice format that allows you interacting with your countries with the most geographical softwares.
5) Create und use your own tiles
This approach is the most performant solution but not the simplest to implement.
Here is a very nice tutorial explaining five approaches. But I think the simplest is using TileMill.
6) Using a mapserver
If you are not familiar with mapservers, this should only be considered when you are going to implement an extensive application. Nice Mapservers are Deegree and the popular Geoserver.
All of these approaches have their pros und cons but I think one of these solutions will fit your needs and I wish you the best successes!
You can use google Geo Chart. You can highlight any country you wanted.
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
'packages':['geomap'],
// Note: you will need to get a mapsApiKey for your project.
// See: https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings
'mapsApiKey': 'AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY'
});
google.charts.setOnLoadCallback(drawMap);
function drawMap() {
var data = google.visualization.arrayToDataTable([
['Country', 'Popularity'],
['Germany', 200],
['United States', 300],
['Brazil', 400],
['Canada', 500],
['France', 600],
['RU', 700]
]);
var options = {};
options['dataMode'] = 'regions';
var container = document.getElementById('regions_div');
var geomap = new google.visualization.GeoMap(container);
geomap.draw(data, options);
};
</script>
</head>
<body>
<div id="regions_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
For more info here is the link
https://developers.google.com/chart/interactive/docs/gallery/geomap?csw=1

How to drag features in Open Layers 3?

In the OL3 examples I can drag objects and drop on the map, but I want to move/resize/rotate things that are already on the map like ol.geom.Point and other ol.geom objects. What is the OL3 way do do this?
Example in OL2:
OpenLayers.Control.DragFeature(layer)
Not sure why the example on OL3 website is so complicated. Dragging vector objects can be easily achieved using new ol.interaction.Modify.
Here is a simpler working example: jsFiddle
In short, if you marker was:
var pointFeature = new ol.Feature(new ol.geom.Point([0, 0]));
You can define modify interaction as :
var dragInteraction = new ol.interaction.Modify({
features: new ol.Collection([pointFeature]),
style: null
});
map.addInteraction(dragInteraction);
You can then get a event for getting the new location of marker after drag like so:
pointFeature.on('change',function(){
console.log('Feature Moved To:' + this.getGeometry().getCoordinates());
},pointFeature);
Take a look at the modify interaction (example). Though rotation is not yet supported.
I have create a simple lib that add drag interaction to openlayers 4 by slightly changing this official example: https://openlayers.org/en/latest/examples/custom-interactions.htm
you can find the lib here :
https://gist.github.com/kingofnull/0ad644be69d8dd43c05721022ca5c3a5
and you should simply add it this way:
var map = new ol.Map({
interactions: ol.interaction.defaults().extend([new ol.interaction.Drag(),])
});
Update
I test the translate and it works in openlayer 4 and there is no need for a custom interaction. keep it in mind if you going to combine it with modify interaction you should add it before modify. here is my final code:
var map = new ol.Map({...});
var featureDrager = new ol.interaction.Translate();
var modify = new ol.interaction.Modify({...});
map.addInteraction(featureDrager);
map.addInteraction(modify);

How to avoid overlap of markers

I've a lot markers inside of a cloudemade map. Sometimes there is a number ob markers at the same location. I use the cluster functionallity but how can I avoid that there are more then one marker on the same coordinats? In such a case, I simply want to have the marker beside each other.
var myMarkerLatLng = new CM.LatLng(<?php echo($rowg['lat'].','.$rowg['lon']); ?>);
var myMarker = new CM.Marker(myMarkerLatLng, {
title: "<?php echo($row['name']); ?>",
icon: icon
});
Our old Web Maps API is deprecated. Please use Leaflet instead of it. You can find good code examples here http://leafletjs.com/examples/quick-start.html. Is is free and easy customisable.