I am currently working on a program that pulls countries and coordinates from a database. I am pinning them on a map after gathering them. I am having no trouble when receiving both the coordinates and the country but when the coordinates aren't available I can't pin on the map just based on the country. I was hoping there was a leaflet method that would allow me to geolocate solely based on a country that would pin in the middle of the country.
Any help is appreciated, thanks!
There is no core Leaflet method for doing this. However, there are some (3rd-party) Leaflet geocoding plugins that might do the trick. Take at look here: http://leafletjs.com/plugins.html#geocoding. Specifically, there is a geonames plugin that looks especially promising: https://github.com/consbio/Leaflet.Geonames.
Leaflet or not, this should be fairly easy to accomplish using a simple RESTful API call. Here's a Plunker where this is done: https://plnkr.co/edit/B2OF0D1nlBuNW6r2rqVL
Below is the operative section:
$( document ).ready(
function() {
// Get the latlng from rest countries
getCountryLocation = function() {
$('#country').html( $('#country_input').val() );
$.ajax(
{
url: "https://restcountries.eu/rest/v2/name/" + $('#country_input').val() + "?fullText=true",
success: function( result ) {
var latlng = result[0].latlng;
$("#latlng").html( latlng[0] + ", " + latlng[1] );
}
}
);
}
// Do the inital setup
getCountryLocation();
$('#go').click(
getCountryLocation
);
}
);
Related
I am new to Mapbox. I am getting trouble while reading the features. I am only able to get the features which are listed or shown on current Viewport. I need to ask if there is any event in mapbox to check if all tiles/Features loaded inside my selected polygon so I can read all features between polygon. The code I am using for reading features is
map.on("idle", () => {
var features = map.queryRenderedFeatures(
[northEastPointPixel, southWestPointPixel],
{
layers: ["MyLayer"],
}
);
});
I am able to display contents of clustered markes but could not display the contents of a single marker.
Please find the below code, where else statement will handle the single marker.
map.eachLayer(function(marker) {
if (marker.getChildCount) { // to get cluster marker details
console.log('cluster length ' + marker.getAllChildMarkers().length);
} else {
// how to display the contents of a single marker ??
alert(marker.options.title); // doesn't work
}
Thanks.
Remember that map.eachLayer() works on every layer of the map. This includes popups and the map tile layer, as well as markers and clusters of markers. Not all these types of layers will have the same options as markers or clusters. You will need to test to check whether each layer is a Marker, a cluster, or something else. Also, remember that markers may not necessarily have a title set.
This works for me:
map.eachLayer(function(layer) {
if(layer.options && layer.options.pane === "markerPane") {
alert("Marker [" + layer.options.title + "]");
}
});
I'm using Mapquest's Javascript API for leaflet.
My code looks like this:
dir = MQ.routing.directions()
.on('success',
function (data) {
console.log(data);
var legs = data.route.legs;
var maneuvers;
if (legs && legs.length) {
maneuvers = $.map(legs[0].maneuvers,
function(m) {
return new Maneuvers(m);
});
self.maneuvers(maneuvers);
}
});
dir.route({
locations: [
self.from(),
self.to()
]
});
map.addLayer(MQ.routing.routeLayer({
directions: dir,
fitBounds: true
}));
The results I get looks like this:
Although, this looks good, the icons don't look anything like the Get Direction module on mapquest.com
How can I change the icons so that they look more modern?
Our new static map v5 is now in beta, this includes a new customizable icon service. check it out:
https://developer.mapquest.com/documentation/static-map-api/v5/getting-started/
There is a new icon service coming in the not too distant future with more modern icons. It will be a companion to a new static map version. Sorry, no eta yet.
Another developer created our original map but I'm tasked with making some changes. One of these is making sure the activated marker is brought to the front when clicked on (where it is partially overlapped by other markers).
The developers have used mapbox 2.2.2.
I have looked at leafletjs's docs, have followed some instructions on other posted solutions (e.g. solution one and solution two). Neither of these makes any difference.
Examining the marker in Chrome's console I can see the value of options.zIndexOffset is being set (10000 in my test case). I've even set _zIndex to an artificially high value and can see that reflected in the marker's data structure. But visually nothing is changing.
This is how the map is set up initially. All features are from a single geojson feed:
L.mapbox.accessToken = '<access token here>';
var map = L.mapbox.map('map', 'map.id', {
}).setView([37.8, -96], 3);
var jsonFeed, jsonFeedURL;
var featureLayer = L.mapbox.featureLayer()
.addTo(map)
.setFilter(function (f) {
return false;
});
$.getJSON(jsonFeedURL, function (json) {
jsonFeed = json;
jsonFeedOld = json;
// Load all the map features from our json file
featureLayer.setGeoJSON(jsonFeed);
}).done(function(e) {
// Once the json feed has loaded via AJAX, check to see if
// we should show a default view
mapControl.activateInitialItem();
});
Below is a snippet of how I had tried setting values to change the z-index. When a visual marker on the featureLayer is clicked, 'activateMarker' is called:
featureLayer.on('click', function (e) {
mapControl.activateMarker(e);
});
The GEOjson feed has urls for the icons to show, and the active marker icon is switched to an alternative version (which is also larger). When the active feature is a single Point I've tried to set values for the marker (lines commented out, some of the various things I've tried!)
activateMarker: function (e) {
var marker = e.layer;
var feature = e.layer.feature;
this.resetMarkers();
if (feature.properties.hasOwnProperty('icon')) {
feature.properties.icon['oldIcon'] = feature.properties.icon['iconUrl'];
feature.properties.icon['iconUrl'] = feature.properties.icon['iconActive'];
feature.properties.icon['oldIconSize'] = feature.properties.icon['iconSize'];
feature.properties.icon['iconSize'] = feature.properties.icon['iconSizeActive'];
}
if (feature.geometry.type == 'Point') {
marker.setZIndexOffset(10001);
marker.addTo(featureLayer);
}
//featureLayer.setGeoJSON(jsonFeed);
}
Any advice would be greatly appreciated! I'm at the point where I don't know what else to try (and that's saying something).
What probably happens is that you just flush your markers with the last call to .setGeoJSON():
If the layer already has features, they are replaced with the new features.
You correctly adjust the GeoJSON data related to your icon, so that when re-created, your featureLayer can use the new values to show a new icon (depending on how you configured featureLayer).
But anything you changed directly on the marker is lost, as the marker is removed and replaced by a new one, re-built from the GeoJSON data.
The "cleanest" way would probably be to avoid re-creating all features at every click.
Another way could be to also change something else in your GeoJSON data that tells featureLayer to build your new marker (through the pointToLayer option) with a different zIndexOffset option.
If you have 2 pushpins on 'London' at the same geolocation, is there anything in the API to move them apart so they are both visible?
I can only find documentation on their old map points API which had PreventIconCollisions, this is what I want but can't see any reference to this in the new API.
I am using the JavaScript API.
So if I understand correctly, you have similar information on the same location, it this correct?
In order to display both information, you will have two options:
Merge information in the textbox using an appropriate way to present the information inside this ui element (using your own tabbed infobox for example)
Decluster the point manually when you're at a certain level of zoom
There is no default property to set this and it would really messy to do this on many pushpins, but in the main idea, you would have to: detect viewchangeend event, if you're at a certain level of zoom (or higher zoom level) then you're declustering them (I call it decluter nearby pushpins).
// Bind pushpin mouseover.
Microsoft.Maps.Events.addHandler(pin, 'mouseover', function (e) {
var currentPin = e.target;
currentPin.setOptions({ visible: false });
var currentLocation = currentPin.getLocation().clone();
var currentPoint = bmGlobals.geo.map.tryLocationToPixel(currentLocation);
if (currentPin.associatedCluster.length == 2) {
// Display the first pushpin
var pinA = createPin(currentPin.associatedCluster[0]);
var locA = bmGlobals.geo.map.tryPixelToLocation(new Microsoft.Maps.Point(currentPoint.x - pinA.getWidth(), currentPoint.y));
pinA.setLocation(locA);
bmGlobals.geo.layerClusteredPin.push(pinA);
// Display the second pushpin
var pinB = createPin(currentPin.associatedCluster[1]);
var locB = bmGlobals.geo.map.tryPixelToLocation(new Microsoft.Maps.Point(currentPoint.x + pinB.getWidth(), currentPoint.y));
pinB.setLocation(locB);
bmGlobals.geo.layerClusteredPin.push(pinB);
}
});
I will try to write a bing maps module about this, but in the fact, you'll have to get your clustered pushpins (or your own pushpin that has two associated data object) and then you will have to set their position based on the rendering on the client side.
I know this question is really old, but if someone is looking for something similar (clustering the pins) here is a good start: http://rtsinani.github.io/PinClusterer/