I want to retrieve the total road distance of a route between 2 locations using a TomTom map (Leaflet) and show it underneath the map...
Does anyone have a working example of that?
My code so far is:
<script>
tomtom.setProductInfo('GeoDE', '4.44.7');
var map = tomtom.map('map', {
key: 'myKey'
});
tomtom.routingKey('myKey');
tomtom.routing({
traffic: false
})
.locations('48.78270899,9.182864184:47.78270899,8.182864184')
.go().then(function(routeJson) {
var route = tomtom.L.geoJson(routeJson, {
style: {color: '#0000ff', opacity: 0.6}
}).addTo(map);
map.fitBounds(route.getBounds(), {padding: [10, 10]});
});
</script>
routeJson contains details of what you need: lengthInMeters and TravelTimeInSeconds
Related
I need to create a circle around a point where a user clicks. How would I do this? Every tutorial shows extracting a circle from a geojson source and not creating one. Need to be able to edit the radius as well.
Did you try something yourself? Following the mapbox examples you should be able to get an idea of how to build something like that.
You would need to do 3 things:
Create a source that holds the data
Create a layer of type "circle" for displaying the data as circles
On every click of the user, extract the "latitude, longitude" and add a point to your data list. Then display all of those points as a circle on the map.
This is an example of how I would have coded that: https://jsfiddle.net/andi_lo/495t0dx2/
Hope that helps you out
mapboxgl.accessToken = '####';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/light-v9', //stylesheet location
center: [-74.50, 40], // starting position
zoom: 9 // starting zoom
});
map.on('load', () => {
const points = turf.featureCollection([]);
// add data source to hold our data we want to display
map.addSource('circleData', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [],
},
});
// add a layer that displays the data
map.addLayer({
id: 'data',
type: 'circle',
source: 'circleData',
paint: {
'circle-color': '#00b7bf',
'circle-radius': 8,
'circle-stroke-width': 1,
'circle-stroke-color': '#333',
},
});
// on user click, extract the latitude / longitude, update our data source and display it on our map
map.on('click', (clickEvent) => {
const lngLat = new Array(clickEvent.lngLat.lng, clickEvent.lngLat.lat);
points.features.push(turf.point(lngLat));
map.getSource('circleData').setData(points);
});
});
#map {
height: 500px;
}
<div id="map"></div>
in index.html I woluld like to add two Heatmaps users can see by checkbox in menu top right corner.
menu show other stuff by code like this
layerControl.addOverlay(geojson, "H2OpenMap");
in this portion of the page (line 383 to line 397)
$.getJSON('api.php', {'wells': '1'}, function(remoteData){
var geojson = L.geoJson(remoteData, {
pointToLayer: function (feature, latlng) {
var icon = chooseIcon(feature['properties']);
var marker = L.marker(latlng, {icon: new h2icon( {iconUrl: icon} )} );
var markerText = buildPopup(feature, true, latlng);
marker.bindPopup(markerText);
return marker;
}
}).addTo(map);
layerControl.addOverlay(geojson, "H2OpenMap");
map.fitBounds(geojson.getBounds(), {'padding': [10,10]});
});
First heat should use data from the same code before, selected by
if(feature['drinking_water'] == 'yes' ) {...
}
Second heat should use data from the same code before, selected by
if(feature['drinking_water'] == 'no' ) {...
}
The goal is to have two heat maps, one for clean water resources the other for not clean water resources, both can be selected by ratio button.
I've find this code looks good but I'm not able to give him data to use to create heatmap.....
//--------------------https://www.patrick-wied.at/static/heatmapjs/plugin-leaflet-layer.html-----------//
$.getJSON('api.php', {'wells': '1'}, function(remoteData){
var geojson = L.geoJson(remoteData, {
pointToLayer: function (feature, latlng) {
var heatData = L.marker(latlng);
console.log(heatData);
//var heatData = L.marker([{lat: new latlng(lat), lng: new latlng(lng)}]);
}})});
/*var testData = {
max: 8,
data: [{lat: 24.6408, lng:46.7728, count: 3},{lat: 50.75, lng:-1.55, count: 1}, ...]
};*/
var cleanWater = heatData;// mettere in un array solo la posizione degli elementi che rispettano la seguente condizione: feature['drinking_water'] == 'yes'
var cfg = {
// radius should be small ONLY if scaleRadius is true (or small radius is intended)
// if scaleRadius is false it will be the constant radius used in pixels
"radius": 2,
"maxOpacity": .8,
// scales the radius based on map zoom
"scaleRadius": true,
// if set to false the heatmap uses the global maximum for colorization
// if activated: uses the data maximum within the current map boundaries
// (there will always be a red spot with useLocalExtremas true)
"useLocalExtrema": true,
// which field name in your data represents the latitude - default "lat"
latField: 'lat',
// which field name in your data represents the longitude - default "lng"
lngField: 'lng',
// which field name in your data represents the data value - default "value"
valueField: 'count'
};
var heatmapLayer = new HeatmapOverlay(cfg);
var map = new L.Map('map-canvas', {
center: new L.LatLng(25.6586, -80.3568),
zoom: 4,
layers: [baseLayer, heatmapLayer]
});
heatmapLayer.setData(cleanWater);
//------------------------//--------------------//--------------------//--------------------//--------------------*/
in the root project it's following file with complete code:
https://github.com/H2OpenMap/map/blob/master/index_heat_test.html
Simplifying your problem I try to suggest you this example ...
http://bl.ocks.org/d3noob/raw/8973028/
This a simple code that implements a Leaflet heat map.
If you see at the source code ...
<!DOCTYPE html>
<html>
<head>
<title>Simple Leaflet Map with Heatmap </title>
<meta charset="utf-8" />
<link
rel="stylesheet"
href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"
/>
</head>
<body>
<div id="map" style="width: 600px; height: 400px"></div>
<script
src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js">
</script>
<script
src="http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js">
</script>
<script src="2013-earthquake.js"></script>
<script>
var map = L.map('map').setView([-41.5546,174.146], 10);
mapLink =
'OpenStreetMap';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© ' + mapLink + ' Contributors',
maxZoom: 18,
}).addTo(map);
var heat = L.heatLayer(quakePoints,{
radius: 20,
blur: 15,
maxZoom: 17,
}).addTo(map);
</script>
</body>
.... you'll find that the data is simulated with a coordinate array that you can see here ...
http://bl.ocks.org/d3noob/raw/8973028/2013-earthquake.js
I think that you've to convert your geojson data in this format and all will work!
Cesare
I'm working on a map with a few circleMarkers. When a user is clickin on one of this circleMarker, I would like to center the map on this circleMarker and to zoom in. It works when I try this on multipolygon layers, but I didn't succeed on circleMarkers. Does anyone can help me?
Here is the code for my circleMarkers:
<script>
var map = L.map('map', {
center: [41.8, 12.5],
zoom: 5,
zoomControl:true, maxZoom:15, minZoom:4,
});
var feature_group = new L.featureGroup([]);
var raster_group = new L.LayerGroup([]);
var basemap = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri',
});
basemap.addTo(map);
function style1(feature) {
return {
weight: 2,
radius: 10,
opacity: 1,
color: 'black',
weight: 1,
fillOpacity: 1,
fillColor: 'red'
};
}
L.geoJson(villes, {
style: style1,
pointToLayer: function (feature, latlng)
{
return L.circleMarker(latlng).bindLabel( feature.properties.Name, {className: "ville", noHide: true });
}
}
)
.addTo(map)
.showLabel;
</script>.
Here is a link to the complete map.
Thank you.
This can be achieved really simply.
Let's assume marker points to your leaflet marker and map to your leaflet map.
Quick way (recommended)
marker.on("click", function(event) {
map.setView(marker.getLatLng(), 16);
}, marker);
Here, I don't even compute the needed zoom level, because I assume leaflet will have to zoom to its max level anyway.
I could also have added my marker to a L.LayerGroup, even if the main point of a LayerGroup is to group multiple markers.
Anyhow, the more precise way
marker.on("click", function(event) {
map.setView(marker.getLatLng(), map.getBoundsZoom(layerGroup.getBounds());
}, marker);
Note that the quick way will do it nicely too. The second solution might seem more precise but it also slower, and implies a use of LayerGroup which is not the way it has been designed to work (create a new layergroup for each marker).
Don't forget to take yout time reading the docs, it's well-designed and pretty easy to understand.
I find the solution:
function onClick(e) {map.setView(this.getLatLng(),15);}
L.geoJson(villes, {
style: style1,
pointToLayer: function (feature, latlng)
{
return L.circleMarker(latlng).bindLabel( feature.properties.Name, {className: "ville", noHide: true }).on('click', onClick);
}
}
)
.addTo(zoom1)
.showLabel;
Thanks Stranded Kid for your help.
I am using mapbox.js to render a mapbox map. I am trying to load geojson from my server that contain either a country polygon or a city coordinates (lon,lat).
I have been able to style the country polygons but not the city points/markers.
I am not able to modify the geojson to use mapbox simplestyle
Here is the code executed when the page loads (I changed the mapbox map ID):
var southWest = L.latLng(-90, -360), northEast = L.latLng(90, 360);
var bounds = L.latLngBounds(southWest, northEast);
var map = L.mapbox.map('map', 'MapboxMapID', { zoomControl: false, infoControl: true, detectRetina: true, maxBounds: bounds, minZoom: 2, legendControl: {position: 'topright'}});
new L.Control.Zoom({ position: 'bottomright' }).addTo(map);
map.fitBounds(bounds);
var locationsGroup = L.featureGroup().addTo(map);
and then when the user selects a country or city with a selectbox:
$("#select2-search-up").on("change", function (e) {
if (e.added) {
var location = L.mapbox.featureLayer().loadURL('/citiesCountriesID/' + e.added.id).on('ready', function(featLayer) {
this.eachLayer(function(polygon) {
polygon.setStyle({
stroke:false, fillColor:'red', fillOpacity:0.2
});
});
});
locationsGroup.addLayer(location);
} else {
locationsGroup.eachLayer(function (layer) {
if (layer._geojson[0]._id == e.removed.id) {
locationsGroup.removeLayer(layer);
}
});
}
});
Ideally I would like to display a different icon that the standard marker, but I could do with a small red square
Thank you for your inputs
In this example I did some circle markers but I'm pretty sure you can do other basic svg shps or your own .png pretty easy. http://bl.ocks.org/mpmckenna8/db2eef40314fe24e9177
This example from Mapbox also shows how to use a icon from their icon Library which has a lot of choices also. https://www.mapbox.com/mapbox.js/example/v1.0.0/l-mapbox-marker/
It might also help to see some of your geojson structure to see why it can't use simplestyle
In my bl.ocks example I loaded each of the geojson datasets separately
var begin = L.geoJson(start,{
pointToLayer:function(feature, latlng){
return L.circleMarker(latlng,{
radius:9,
fillColor: "orange",
fillOpacity:.7
})
}
})
Is how I set up my circles and I set a different L.geoJson to the other data which I left as the default markers.
I am using the Mapbox template: DC Properties
I am calling 3 tiles, including the base tile.
I have another tile of markers, but I would like to change this to Leaflet dataset and clustering.
Having trouble integrating the Leaflet map and marker call into my Mapbox code below:
<script type="text/javascript">
var main = Map('map', {
api: 'http://a.tiles.mapbox.com/v3/test.map-j9pcd8xs.jsonp',
center: {
lat: 40.593000,
lon: -73.743126406355,
zoom: 10
},
zoomRange: [8, 15],
features: [
'zoomwheel',
'tooltips',
'movetips',
'zoombox',
'zoompan',
'share'
]
});
main.layers({
income: {api: 'http://a.tiles.mapbox.com/v3/test.incomedec3.jsonp',
center: {
ease: 500
}
},
Please help!
I have another tile of markers, but I would like to change this to Leaflet dataset and clustering.
That example is built using Modest Maps, you'll need to rewrite it to use Leaflet.