Saving a div contains a geomap as an Image - javascript

I want to save the showing map in my div as an image. I tried the following code but it does not show the map content but just the map contollers.
I used the snippet but Actually I don't know why it doesn't show the appened picture on the snippet. it shows the appened picture (without map content) for me.
$(function () {
var map = L.map('map').setView([10.505, 20], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
map.zoomControl.setPosition('bottomright');
});
$("#geo-btn").on("click", function (e) {
var container = L.DomUtil.get('map');
if (container != null) {
container._leaflet_id = null;
}
var map = L.map('map').setView([10.505, 20], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
var states = JSON.parse(`[{
"type": "Feature",
"properties": { "party": "Republican" },
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-97.22, 48.98],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": { "party": "Democrat" },
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.06, 40.99],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}]`);
L.geoJSON(states, {
style: function (feature) {
switch (feature.properties.party) {
case 'Republican': return { color: "#ff0000" };
case 'Democrat': return { color: "#0000ff" };
}
}
}).addTo(map);
});
$("#img-save").on("click", function () {
html2canvas(document.getElementById("map")).then(canvas => {
document.body.appendChild(canvas);
});
});
#map {
height: 500px;
border: red solid 1px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.8.0/dist/leaflet.css"
integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ=="
crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet#1.8.0/dist/leaflet.js"
integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
crossorigin=""></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<title>Geo</title>
</head>
<body>
<body>
<button id="geo-btn"> Click to Show</button>
<button id="img-save">Show Image</button>
<div id="map"></div>
<div id="result-img"></div>
</body>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</html>

I think this should work for you
$(function() {
const map = L.map('map').setView([10.505, 20], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
map.zoomControl.setPosition('bottomright');
});
$("#geo-btn").on("click", function(e) {
const container = L.DomUtil.get('map');
if (container != null) {
container._leaflet_id = null;
}
const map = L.map('map').setView([10.505, 20], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
const states = JSON.parse(`[{
"type": "Feature",
"properties": { "party": "Republican" },
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-97.22, 48.98],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": { "party": "Democrat" },
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.06, 40.99],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}]`);
L.geoJSON(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican':
return {
color: "#ff0000"
};
case 'Democrat':
return {
color: "#0000ff"
};
}
}
}).addTo(map);
});
$("#img-save").on("click", function() {
const clone = document.getElementById("map").cloneNode(true);
document.getElementById('foo').appendChild(clone);
});
#map {
height: 500px;
border: red solid 1px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.8.0/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet#1.8.0/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<title>Geo</title>
</head>
<body>
<button id="geo-btn"> Click to Show</button>
<button id="img-save">Show Image</button>
<div id="map"></div>
<div id="result-img"></div>
</body>
<div id="foo"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</html>
you just need these lines:
const clone = document.getElementById("map").cloneNode(true);
document.getElementById('foo').appendChild(clone);
I hope this helps

Check out: https://jsfiddle.net/PatrickHume/1rscqwkL/1/, as the image download doesn't work in SO's code runner, click the 'Click to Show' first then click 'Show Image' and it will download the image
it uses: https://github.com/tsayen/dom-to-image
and https://github.com/eligrey/FileSaver.js/
$(function() {
const map = L.map('map').setView([10.505, 20], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
map.zoomControl.setPosition('bottomright');
});
$("#geo-btn").on("click", function(e) {
const container = L.DomUtil.get('map');
if (container != null) {
container._leaflet_id = null;
}
const map = L.map('map').setView([10.505, 20], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
const states = JSON.parse(`[{
"type": "Feature",
"properties": { "party": "Republican" },
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-97.22, 48.98],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": { "party": "Democrat" },
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.06, 40.99],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}]`);
L.geoJSON(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican':
return {
color: "#ff0000"
};
case 'Democrat':
return {
color: "#0000ff"
};
}
}
}).addTo(map);
$("#img-save").on("click", function() {
const clone = document.getElementById("map").cloneNode(true);
document.getElementById('foo').appendChild(clone);
domtoimage.toBlob(document.getElementById('foo'))
.then(function(blob) {
window.saveAs(blob, 'my-node.png');
});
});
});
#map {
height: 500px;
border: red solid 1px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.8.0/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<title>Geo</title>
</head>
<body>
<button id="geo-btn"> Click to Show</button>
<button id="img-save">Show Image</button>
<div id="map"></div>
<div id="result-img"></div>
</body>
<div id="foo"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://unpkg.com/leaflet#1.8.0/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
<script src="https://cdn.bootcss.com/dom-to-image/2.6.0/dom-to-image.min.js"></script>
</html>
Hope this helps

Related

I am trying to visualise some datapoint on a map using leaflet javascript library.Can you tell me whats wrong with my code?

I am trying to visualize geojson data from URL to my frontend. I am using leaflet library and a project I found as my template on which I have changed the database. Variables AvgMonthlyKL and Suburb do not exist and I do not care about the radius just to display the data point.
Everything is fine with the database and the url which is displaying geojson. I have removed all part of the code peace by peace and tried to replace those variables with others existing from the database but I can not make the datapoint to show up. Please help.
function main_map_init(map, options) {
var dataset = new L.GeoJSON.AJAX("{% url 'waterconsumption' %}", {
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, {
fillColor: 'teal',
color: '#537898',
weight: 1,
fillOpacity: 0.5
}).on({
mouseover: function(e) {
this.setStyle({color: 'yellow'});
},
mouseout: function(e) {
this.setStyle({color: '#537898'});
}
});
},
onEachFeature: function(feature, layer) {
var radius = calcPropRadius(feature.properties.AvgMonthlyKL);
var popupText = "<strong>" + feature.properties.Suburb + "</strong>";
layer.setRadius(radius);
layer.bindPopup(popupText, { offset: new L.Point(0, -radius) });
}
}).addTo(map);
Geojson sample:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"properties":{
"device_identifier":"f5ea3f85ed562fcde4e2110d14c5ff1f",
"battery":"",
"enqueued":"2019-08-06T10:46:57Z",
"DateTime":"2019-08-07T13:27:54.198Z",
"model":"waterwatchapp.waterconsumption"
},
"id":13,
"geometry":{
"type":"Point",
"coordinates":[
12.540556907653999,
55.748844146729
]
}
}
]
}
This is how you would do if you had the geojson stored locally. By using Leaflet.AJAX the steps are almost identical. Use the pointToLayer similarly with L.geoJSON.
<!DOCTYPE html>
<html>
<head>
<title>Quick Start - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin=""></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js"></script>
</head>
<body>
<div id="mapid" style="width: 100%; height: 100vh;"></div>
<script>
var mymap = L.map('mapid').setView([12.5,
55.748844146729
], 1);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(mymap);
var geojsonFeature = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"device_identifier": "f5ea3f85ed562fcde4e2110d14c5ff1f",
"battery": "",
"enqueued": "2019-08-06T10:46:57Z",
"DateTime": "2019-08-07T13:27:54.198Z",
"model": "waterwatchapp.waterconsumption"
},
"id": 13,
"geometry": {
"type": "Point",
"coordinates": [
12.540556907653999,
55.748844146729
]
}
}]
};
L.geoJSON(geojsonFeature, {
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, {
fillColor: 'teal',
color: '#537898',
weight: 1,
fillOpacity: 0.5
}).on({
mouseover: function(e) {
this.setStyle({
color: 'yellow'
});
},
mouseout: function(e) {
this.setStyle({
color: '#537898'
});
}
});
},
}).addTo(mymap);
</script>
</body>
</html>

The google maps isLocationOnEdge() method is not working for data layer features

I am trying to get the lines geometries passing from the clicked point. When I call google.maps.geometry.poly.isLocationOnEdge by adding the data
directly on map for those features I am getting a successful result.
You can see the sample code from this JSFiddle1
code snippet (from fiddle1):
<!DOCTYPE html>
<html>
<head>
<title>GOOGLE Map</title>
<link rel="icon" href="google.jpg" type="image/gif" sizes="16x16">
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
#map {
height: 100%;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map">
</div>
<script>
var map;
var TILE_SIZE = 256;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lng: 73.76606472,
lat: 46.7578125
},
zoom: 21
});
// map.data.loadGeoJson(href = "groupgeo.json");
// map.data.addListener('click', identifyFeatures );
map.addListener('click', identifyFeatures);
var cord = [{
lat: 44.7578125,
lng: 72.76606472
},
{
lat: 46.7578125,
lng: 73.76606472
}
];
var flightPath = new google.maps.Polyline({
path: cord,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2
});
flightPath.setMap(map);
function identifyFeatures(evt) {
var featuresHits = [];
if (google.maps.geometry.poly.isLocationOnEdge(evt.latLng, flightPath, 0.123444)) {
featuresHits.push(flightPath);
}
alert("Total Features: " + featuresHits.length);
};
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDxBykE_KdCA6Etkewrera3hO3qep0IOxM&callback=initMap" async defer></script>
</body>
</html>
But when I call google.maps.geometry.poly.isLocationOnEdge by adding the
features on the map via a data layer I am getting this method's result is always
false (its not even depending on whatever tolerance I had set)
You can see the sample code from this JSFiddle2.
code snippet (from fiddle2):
<!DOCTYPE html>
<html>
<head>
<title>GOOGLE Map</title>
<link rel="icon" href="google.jpg" type="image/gif" sizes="16x16">
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
#map {
height: 100%;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map">
</div>
<script>
var map;
var TILE_SIZE = 256;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lng: 73.76606472,
lat: 46.7578125
},
zoom: 21
});
var geoJSON = {
"type": "Feature",
"id": "red_line.963",
"geometry": {
"type": "LineString",
"coordinates": [
[72.76606472, 44.7578125],
[73.76606472, 46.7578125]
]
},
"geometry_name": "geometry",
"properties": {
"text_value": null,
"redline_id": 146
}
};
map.data.addGeoJson(geoJSON); //adding data layer
map.addListener('click', identifyFeatures);
function identifyFeatures(evt) {
var featuresHits = [];
map.data.forEach(function(feature) {
var type = feature.getGeometry().getType();
if ("LineString" == type) {
var polygonCords = [];
var pointOnLine = null;
feature.getGeometry().forEachLatLng(function(latlng) {
polygonCords.push(latlng);
});
var polyline = new google.maps.Polyline({
paths: polygonCords,
});
if (google.maps.geometry.poly.isLocationOnEdge(evt.latLng, polyline, 0.123444)) {
featuresHits.push(feature);
}
}
});
alert("Total Features: " + featuresHits.length);
};
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDxBykE_KdCA6Etkewrera3hO3qep0IOxM&callback=initMap" async defer></script>
</body>
</html>
Can anyone tell me why this is happening?
You have a typo in the creation of your google.maps.Polyline, that doesn't have a paths property, it should be path (the google.maps.Polygon has a paths property):
var polyline = new google.maps.Polyline({
paths: polygonCords,
});
should be:
var polyline = new google.maps.Polyline({
path: polygonCords,
});
proof of concept fiddle
code snippet:
<!DOCTYPE html>
<html>
<head>
<title>GOOGLE Map</title>
<link rel="icon" href="google.jpg" type="image/gif" sizes="16x16">
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
#map {
height: 100%;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map">
</div>
<script>
var map;
var TILE_SIZE = 256;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lng: 73.76606472,
lat: 46.7578125
},
zoom: 21
});
var geoJSON = {
"type": "Feature",
"id": "red_line.963",
"geometry": {
"type": "LineString",
"coordinates": [
[72.76606472, 44.7578125],
[73.76606472, 46.7578125]
]
},
"geometry_name": "geometry",
"properties": {
"text_value": null,
"redline_id": 146
}
};
map.data.addGeoJson(geoJSON); //adding data layer
map.addListener('click', identifyFeatures);
function identifyFeatures(evt) {
var featuresHits = [];
map.data.forEach(function(feature) {
var type = feature.getGeometry().getType();
if ("LineString" == type) {
var polygonCords = [];
var pointOnLine = null;
feature.getGeometry().forEachLatLng(function(latlng) {
polygonCords.push(latlng);
});
var polyline = new google.maps.Polyline({
path: polygonCords,
});
if (google.maps.geometry.poly.isLocationOnEdge(evt.latLng, polyline, 0.123444)) {
featuresHits.push(feature);
}
}
});
alert("Total Features: " + featuresHits.length);
};
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDxBykE_KdCA6Etkewrera3hO3qep0IOxM&callback=initMap" async defer></script>
</body>
</html>

Draw markers on leaflet map from geojson data

How to import geoJson data (with more than 2000 coordinates) into leaflet map?
This is short sample of geo json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ 44.8242557024,20.4048512901 ]
},
"properties": {
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ 44.8242557024,20.4048512901 ]
},
"properties": {
}
},...]
Code I've tried:
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.ie.css" />
<![endif]-->
<style type="text/css">
body {
padding: 0;
margin: 0;
}
html, body, #cmap {
height: 100%;
}
</style>
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
</head>
<body>
<div id="cmap"></div>
<script>
var cupcakeTiles = L.tileLayer('https://api.mapbox.com/v4/mapbox.emerald/page.html?access_token=cj5h2mqa63sc92srx3bu62e2j', {
maxZoom: 18
});
$.getJSON("convertcsv.geojson", function(data) {
var geojson = L.geoJson(data, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.name);cj5h2mqa63sc92srx3bu62e2j
}
});
var map = L.map('map', {
center: [44, 20],
zoom: 7
});
L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
id: 'examples.map-20v6611k'
}).addTo(map);
new L.GeoJSON(meta1nJson).addTo(map);
});
</script>
</body>
</html>
But nothing happens, it is just a gray background. I'm not sure where the mistake is (maybe there is more than one), but probably there is a mistake with importing geojson data and map token.
I'm total beginner at this. Thank in advance.
You seem to have to have many issues in your code. Firstly an element with id 'map' does not exist in your html, so the map layer cannot be placed. You have to add 'cmap' as the id in the below code.
var map = L.map('cmap', {
center: [44, 20],
zoom: 7
});
Also meta1nJson does not seem to be defined in your code, so the below code would not work.
new L.GeoJSON(meta1nJson).addTo(map);
The layer cupcakeTiles seems to be defined but is never added to the map. You also have a stray string in the below code which should be removed.
$.getJSON("convertcsv.geojson", function(data) {
var geojson = L.geoJson(data, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.name); //cj5h2mqa63sc92srx3bu62e2j
}
});

Leaflet does not mark point with geojsonFeatures?

I'm starting on Leaflet API and I hope to add some geometry points to a customer map using GeoJson data. Currently, I used the geojsonFeaturetype present here http://leafletjs.com/examples/quick-start.html
But, when I follow such steps to add the features, the ones does not appears. Below is my html page and code.
<html><head>
<title>Leaflet Quick Start Guide Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css">
</head>
<body class="">
<div id="mapid" style="width: 600px; height: 400px; position: relative;" class="leaflet-container leaflet-fade-anim" tabindex="0"></div>
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script src="https://raw.github.com/calvinmetcalf/leaflet-ajax/master/dist/leaflet.ajax.min.js"></script>
<script>
var mymap = L.map('mapid').setView([51.505, -0.09], 13);
L.tileLayer('https://api.mapbox.com/styles/v1/edsonbarboza/ciqb82pfe000dc1nliqy8sljp/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoiZWRzb25iYXJib3phIiwiYSI6ImNpbTJjMWRuczA5NGx1MGtzbmN6c3NjOHMifQ.FvAMXzmnQ0TIJDDsV6rXAw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.satelity'
}).addTo(mymap);
var myStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
};
//L.marker([51.51, -0.09]).addTo(mymap)
var geojsonFeature = {
"type": "Feature",
"properties": {
"name": "Coors Field",
"amenity": "Baseball Stadium",
"popupContent": "This is where the Rockies play!"
},
"geometry": {
"type": "Point",
"coordinates": [51.51, -0.09]
}
};
var myLayer = L.geoJson().addTo(mymap);
myLayer.addData(geojsonFeature);
<!-- var geojsonLayer = new L.GeoJSON.AJAX("geojson_data.json", {style:myStyle}); -->
<!-- geojsonLayer.addTo(mymap); -->
var popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(mymap);
}
mymap.on('click', onMapClick);
</script>
Thanks for any help.
You must invert the coordinates in the geometry.
var geojsonFeature = {
"type": "Feature",
"properties": {
"name": "Coors Field",
"amenity": "Baseball Stadium",
"popupContent": "This is where the Rockies play!"
},
"geometry": {
"type": "Point",
"coordinates": [-0.09, 51.51]
}
};
Here is your sample with correction
This is specified here

highlight feature with click in mapbox gl

I have a geojson layer of streets that are highlighted when moused-over.
My objective is now to highlight individual streets red with a click event. Only one street should be able to be highlighted at a time, and should remain highlighted until a different street is clicked.
Any idea as to what needs to be added to the following code?
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>HTML markers from geoJSON url</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.css' rel='stylesheet'/>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpbHIxMXA3ejAwNWl2Zmx5aXl2MzRhbG4ifQ.qsQjbbm1A71QzVg8OcR7rQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v8',
center: [37.625224, 55.744537,],
zoom: 13
});
map.on('style.load', function () {
map.addSource('streets', {
"type": "geojson",
"data": "https://iskandarblue.github.io/mapbox/data/simplify_prototype.geojson"
});
map.addLayer({
"id": "m_streets",
"type": "line",
"source": "streets",
"interactive": true,
"layout": {},
"paint": {
"line-color": "#627BC1",
"line-opacity": 0.0,
"line-width": 2.5
}
});
map.addLayer({
"id": "route-hover",
"type": "line",
"source": "streets",
"layout": {},
"paint": {
"line-color": "#f48024",
"line-opacity": 0.9,
"line-width": 2.5
},
"filter": ["==", "rd_name", ""]
});
map.addLayer({
"id" : "street_toggle",
"source": "streets",
"type": "line",
"layout": {"line-join": "round",
"line-cap": "round"},
"paint": {
"line-color": "#FF0000",
"line-opacity": 0.9,
"line-width:": 3.5
}
});
map.on('mousemove', function(e) {
map.featuresAt(e.point, {
radius: 5,
layer: ["m_streets"]
}, function (err, features) {
if (!err && features.length) {
map.setFilter('route-hover', ['==', 'rd_name', features[0].properties.rd_name]);
} else {
map.setFilter('route-hover', ['==', 'rd_name', '']);
}
});
});
map.on('click', function(e) {
map.featuresAt(e.point, {
radius: 5,
layer: ["street_toggle"]
}, function (err, features) {
if (!err && features.length) {
map.setFilter('street_toggle', ['==', 'rd_name', features[0].properties.rd_name]);
} else {
map.setFilter('street_toggle', ['==', 'rd_name', '']);
}
});
});
});
//.addTo(map);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>HTML markers from geoJSON url</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpbHIxMXA3ejAwNWl2Zmx5aXl2MzRhbG4ifQ.qsQjbbm1A71QzVg8OcR7rQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v8',
center: [37.625224, 55.744537, ],
zoom: 13
});
map.on('style.load', function() {
map.addSource('streets', {
"type": "geojson",
"data": "https://iskandarblue.github.io/mapbox/data/simplify_prototype.geojson"
});
map.addLayer({
"id": "m_streets",
"type": "line",
"source": "streets",
"interactive": true,
"layout": {},
"paint": {
"line-color": "#627BC1",
"line-opacity": 0.0,
"line-width": 2.5
}
});
map.addLayer({
"id": "route-hover",
"type": "line",
"source": "streets",
"layout": {},
"paint": {
"line-color": "#f48024",
"line-opacity": 0.9,
"line-width": 2.5
},
"filter": ["==", "rd_name", ""]
});
map.addLayer({
"id": "street_toggle",
"source": "streets",
"type": "line",
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#FF0000",
"line-opacity": 0.9,
"line-width:": 3.5
}
});
map.on('mousemove', function(e) {
map.featuresAt(e.point, {
radius: 5,
layer: ["m_streets"]
}, function(err, features) {
if (!err && features.length) {
map.setFilter('route-hover', ['==', 'rd_name', features[0].properties.rd_name]);
} else {
map.setFilter('route-hover', ['==', 'rd_name', '']);
}
});
});
map.on('click', function(e) {
map.featuresAt(e.point, {
radius: 5,
layer: ["street_toggle"]
}, function(err, features) {
if (!err && features.length) {
map.setFilter('street_toggle', ['==', 'rd_name', features[0].properties.rd_name]);
} else {
map.setFilter('street_toggle', ['==', 'rd_name', '']);
}
});
});
});
//.addTo(map);
</script>
</body>
</html>
If you take a look at the console output when running your code, you should see this error message:
layers.street_toggle.paint.line-width:: unknown property "line-width:"
Because of this error, the street_toggle layer is not being added to the map and the click interaction is not working.
To fix the problem, please change the "line-width:" key to "line-width"(remove the spurious colon inside the quotes)
#Lucas features At() must be a depreciated method? His colon did throw a bug, but it doesn't help him select a road segment, at least at v0.16, right? I use queryRenderedFeatures()
note: I really wish this method had a optional radius parameter - you really have to click precisely on the line.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>HTML markers from geoJSON url</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.16.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.16.0/mapbox-gl.css' rel='stylesheet'/>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpbHIxMXA3ejAwNWl2Zmx5aXl2MzRhbG4ifQ.qsQjbbm1A71QzVg8OcR7rQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v8',
center: [37.625224, 55.744537,],
zoom: 13
});
map.on('style.load', function () {
map.addSource('streets', {
"type": "geojson",
"data": "https://iskandarblue.github.io/mapbox/data/simplify_prototype.geojson"
});
map.addLayer({
"id": "m_streets",
"type": "line",
"source": "streets",
"interactive": true,
"layout": {},
"paint": {
"line-color": "red",
// "line-opacity": 0.0,
"line-width": 2.5
}
});
map.on('click', function(e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['m_streets'] });
if (!features.length) {
return;
}
if (typeof map.getLayer('selectedRoad') !== "undefined" ){
map.removeLayer('selectedRoad')
map.removeSource('selectedRoad');
}
var feature = features[0];
//I think you could add the vector tile feature to the map, but I'm more familiar with JSON
console.log(feature.toJSON());
map.addSource('selectedRoad', {
"type":"geojson",
"data": feature.toJSON()
});
map.addLayer({
"id": "selectedRoad",
"type": "line",
"source": "selectedRoad",
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "yellow",
"line-width": 8
}
});
});
});
</script>
</body>
</html>

Categories

Resources