Mapbox GL js, effectively represent a geojson source by a variable icon - javascript

I have a mapbox source composed by a list of geojson point, each element of this source has a key icon referring to an icon URL:
var featureCollection = {
"type": "FeatureCollection",
"features": [
{
"geometry":{
"type": "Point",
"coordinates": [1,1]
},
"properties": {
"id": 1,
"name": "name1",
"address": "address1",
"icon": "icon1"
}
},
{
"geometry":{
"type": "Point",
"coordinates": [2,2]
},
"properties": {
"id": 2,
"name": "name2",
"address": "address2",
"icon": "icon2"
}
},
{
"geometry":{
"type": "Point",
"coordinates": [3,3]
},
"properties": {
"id": 3,
"name": "name3",
"address": "address3",
"icon": "icon3"
}
},
{
"geometry":{
"type": "Point",
"coordinates": [4,4]
},
"properties": {
"id": 4,
"name": "name4",
"address": "address4",
"icon": "icon1"
}
}
]
}
map.addSource("shops", {
type: "geojson",
data: featureCollection,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
I'd like to plot my features by representing them by their icon variable, a way to do so would be to add as many layers as I have different icons:
map.addLayer({
id: currentLayer,
type: "symbol",
source: "featureCollection",
filter: ["!has", "point_count"],
"layout": {
"icon-image": currentIcon,
"icon-size":1.5
}
});
The thing is I have more than 200 different icons (out of 800 observations), and I really doubt creating 200 different layers is the most effective way to plot my observations. Especially when I'm triggering a function when the user clicks on an layer, so I would also have to define such function as many times as I have different icons.

You can and should create just one layer. icon-image supports data driven styles so you can use "icon-image": "{icon}".
http://jsbin.com/yofiwizuca/1/edit?html,output
This of course assumes you have icons in your Style named icon1, icon2',icon3based on the values of theicon` properties in your GeoJSON.
You could also use https://www.mapbox.com/mapbox-gl-js/style-spec#expressions if you need to manipulate the values.

Related

How to access single polygon created by geoJSON Leaflet

I added a geoJSON object to a map using. It creates around 200 polygons.
const geoJson = L.geoJSON(polygonsJSON).addTo(map);
The geoJSON object has structure:
{
"type": "FeatureCollection",
"name": "polygonsJSON",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"properties": {
"id": "23",
"NameSurname": "Namex Surnamex",
"r/s": "1823-1975"
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
0.000165649338392,
-0.000006827196159
],
[
0.00014822202188,
-0.00002712912158
],
[
0.000138250722226,
-0.000018774789438
],
[
0.000155857701795,
0.000001347472926
],
[
0.000165649338392,
-0.000006827196159
]
]
]
]
}
},
I would like to modify (lets say change color) only one of the polygons based on its ID. How can I access it?
Thank you.

Adding custom icons for each feature in feature collection with mapbox-gl-js

I need to have different custom images for each points in the map using mapbox-gl-js, But I don't find a way to give custom icon for each feature in a feature collection
incidentMarkers = {
"type": "FeatureCollection"
"features": [{
"type": "geojson",
"data": {
"type": "Feature",
"properties": {
},
"geometry": {
"type": "Point",
"coordinates": [
longitude
latitude
]
}
}
},
{
"type": "geojson",
"data": {
"type": "Feature",
"properties": {
},
"geometry": {
"type": "Point",
"coordinates": [
longitude
latitude
]
}
}
}]
}
map.addSource('incidentMarkers', {
"type": "geojson"
"data": incidentMarker
})
window.map.addLayer({
"id": 'incidentMarkers',
"type": "symbol",
"source": 'incidentMarkers'
"layout": {
"icon-image": "image-1",
"icon-size": 0.25,
"icon-allow-overlap": true,
"text-allow-overlap": true
}
})
Now I am adding each point as separate layer for having custom image for each icon, But for having clustering with markers I need to have all markers as same layers, Is there any way to add custom images for each layers
pointsData.forEach (data) ->
window.map.loadImage("#{data.category_image_path}", (e, image) ->
window.map.addImage("image-#{data.id}", image)
incidentMarker = {
"type": "Feature",
"properties": {
},
"geometry": {
"type": "Point",
"coordinates": [
data.longitude
data.latitude
]
}
}
map.addSource('incidentMarkers' + data.id, {
"type": "geojson",
"data": incidentMarker
})
window.map.addLayer({
"id": 'incidentMarkers' + data.id,
"type": "symbol",
"source": 'incidentMarkers' + data.id
"layout": {
"icon-image": "image-#{data.id}",
"icon-size": 0.25,
"icon-allow-overlap": true,
"text-allow-overlap": true
}
})
And if I have more than one marker at same latlng only one marker is showing up, Even I set icon-allow-overlap option to true
If you reference which icon should be used in each feature's properties you can use mapbox' data-driven styling capabilities to use a different icon for each feature:
const geojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {icon: 'image-1'},
geometry: {/* */}
},
{
type: 'Feature',
properties: {icon: 'image-2'},
geometry: {/* */}
}
]
}
// add source
map.addLayer({
type: 'symbol',
source: 'source-id',
layout: {
'icon-image': ['get', 'icon']
}
})
The ['get', 'icon'] is an expression which "gets" the property "icon" from each feature and uses it as the value for icon-image.

Getting error while using 'circle-color' data driven styling in Mapboxgl.js & GeoJSON, but working fine with default color

I am trying to create a map, put data points using GeoJSON and Mapbox.
It works fine when I am using a default color code for all points, but when I try to use data driven styling to put different colors for different property values It is giving errors.
I am using mapboxgl.js.
I get the following errors in Chrome Inspect:
net::ERR_INTERNET_DISCONNECTED
exports.getJSON # ajax.js:33
evented.js:111 Error
at XMLHttpRequest.r.onerror (ajax.js:18)
Please help!
Here are my GeoJSON and HTML files.
mapboxgl.accessToken = 'pk.eyJ1Ijoicml0YW1iaGFyYSIsImEiOiJjajZuNGZjNHUwNHgxMzNwc29hZ2ZkbmRvIn0.4kTuXEpbJBeoN3jCp3pfwQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v9',
center: [-121.403732, 40.492392],
zoom: 10
});
map.on("load", function() {
map.addSource('pH', {
'type': 'geojson',
'data': 'test.json'
});
map.addLayer({
id: 'heat-map',
type: 'circle',
source: 'pH',
paint: {
// 'circle-color': '#f1f075',
'circle-color': {
property: 'value',
stops: [
[6, '#f1f075'],
[10, '#e55e5e']
]
},
"circle-radius": 6,
'circle-opacity': 0.8
},
});
});
GeoJSON file:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": { "value": "7" },
"geometry": {
"type": "Point",
"coordinates": [-121.415061, 40.506229]
}
}, {
"type": "Feature",
"properties": { "value": "8" },
"geometry": {
"type": "Point",
"coordinates": [-121.505184, 40.488084]
}
}, {
"type": "Feature",
"properties": { "value": "9" },
"geometry": {
"type": "Point",
"coordinates": [-121.354465, 40.488737]
}
}]
}
I believe the problem is due to the fact that your values are in the geojson as strings not numbers. When I changed them to numbers as below your example code worked for me
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": { "value": 7 },
"geometry": {
"type": "Point",
"coordinates": [-121.415061, 40.506229]
}
}, {
"type": "Feature",
"properties": { "value": 8 },
"geometry": {
"type": "Point",
"coordinates": [-121.505184, 40.488084]
}
}, {
"type": "Feature",
"properties": { "value": 9 },
"geometry": {
"type": "Point",
"coordinates": [-121.354465, 40.488737]
}
}]
}
If you still get the AJAX error you may need to run a local server ( you can do this with python -m SimpleHTTPServer in your project folder and then load localhost:8000/path/to/index.html in your browser)

How to get access to GeoJSON FeatureCollection objects in JavaScript

I have a URL linking to a JSON file of a GeoJSON FeatureCollection object.
{"type": "FeatureCollection", "features": [{...}, {...}, ...]}
I insert an attribute "properties" into this FeatureCollection object and assign a value "myFeatureCollection" to the key "name".
{"type": "FeatureCollection", "features": [{...}, {...}, ...], "properties": {"name": "myFeatureCollection"}}
Can I get access to the value "myFeatureCollection" from the outside in JavaScript?
In a word, I am seeking a method to achieve the following objective (pseudo-code):
var fc = jsonRead("myJsonUrl");
var fcName = fc.properties.name;
Only if your data is stored in a external JavaScript file:
You need to consider that the file is loaded asynchronously, therefore must implement a function that returns a callback function.
function jsonRead(String url, Function callback){}
Where:
url = Location path where the file exists
(file:///D:/UserName/GeoJSON/data/geo.js).
callback = Callback function which is executed when a previous operation ends.
Within the context of the callback function you can use the file contents, to execute other functions.
I've made a little demo where you can see how it works.
In your local machine, you need these files.
index.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script src="lib/js/reader.js"></script>
</head>
<body>
<ul id="list"></ul>
</body>
</html>
reader.js:
(function ()
{
window.onload = function ()
{
// Calls the jsonRead function. The first parameter is the URL, the second one is a callback function.
jsonRead("file:///D:/YourDirectory/GeoJSON/data/geo.js", function (fc)
{
buildList(fc); // Demo function to build a list with the current data in «fc» parameter.
});
};
function jsonRead(url, callback)
{
var head, script
head = document.getElementsByTagName("head")[0];
script = document.createElement("script");
script.src = url;
script.type = "text/javascript";
head.appendChild(script);
script.onload = function ()
{
callback(freeBus);
};
}
/* Demo */
// Demo function. It uses the external javascript file content.
function buildList(data)
{
var fc = data;
var list, li, i, j, cant, coordinatesCant, ulCoordinates, liCoordinates;
list = document.getElementById("list");
cant = fc.features.length;
for (i = 0; i < cant; i++)
{
li = document.createElement("li");
li.innerHTML = fc.features[i].id;
coordinatesCant = fc.features[i].geometry.coordinates.length;
if (coordinatesCant > 0)
{
ulCoordinates = document.createElement("ul");
for (j = 0; j < coordinatesCant; j++)
{
liCoordinates = document.createElement("li");
liCoordinates.innerHTML = JSON.stringify(fc.features[i].geometry.coordinates[j]);
ulCoordinates.appendChild(liCoordinates);
}
li.appendChild(ulCoordinates);
}
list.appendChild(li);
}
document.body.appendChild(list);
}
})();
geo.js:
var freeBus = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-105.00341892242432, 39.75383843460583],
[-105.0008225440979, 39.751891803969535]
]
},
"properties": {
"popupContent": "This is free bus that will take you across downtown.",
"underConstruction": false
},
"id": 1
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-105.0008225440979, 39.751891803969535],
[-104.99820470809937, 39.74979664004068]
]
},
"properties": {
"popupContent": "This is free bus that will take you across downtown.",
"underConstruction": true
},
"id": 2
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-104.99820470809937, 39.74979664004068],
[-104.98689651489258, 39.741052354709055]
]
},
"properties": {
"popupContent": "This is free bus that will take you across downtown.",
"underConstruction": false
},
"id": 3
}
]
};
var lightRailStop = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"popupContent": "18th & California Light Rail Stop"
},
"geometry": {
"type": "Point",
"coordinates": [-104.98999178409576, 39.74683938093904]
}
}, {
"type": "Feature",
"properties": {
"popupContent": "20th & Welton Light Rail Stop"
},
"geometry": {
"type": "Point",
"coordinates": [-104.98689115047453, 39.747924136466565]
}
}
]
};
var bicycleRental = {
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9998241,
39.7471494
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 51
},
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9983545,
39.7502833
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 52
},
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9963919,
39.7444271
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 54
},
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9960754,
39.7498956
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 55
},
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9933717,
39.7477264
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 57
},
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9913392,
39.7432392
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 58
},
{
"geometry": {
"type": "Point",
"coordinates": [
-104.9788452,
39.6933755
]
},
"type": "Feature",
"properties": {
"popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
},
"id": 74
}
]
};
var campus = {
"type": "Feature",
"properties": {
"popupContent": "This is the Auraria West Campus",
"style": {
weight: 2,
color: "#999",
opacity: 1,
fillColor: "#B0DE5C",
fillOpacity: 0.8
}
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[-105.00432014465332, 39.74732195489861],
[-105.00715255737305, 39.74620006835170],
[-105.00921249389647, 39.74468219277038],
[-105.01067161560059, 39.74362625960105],
[-105.01195907592773, 39.74290029616054],
[-105.00989913940431, 39.74078835902781],
[-105.00758171081543, 39.74059036160317],
[-105.00346183776855, 39.74059036160317],
[-105.00097274780272, 39.74059036160317],
[-105.00062942504881, 39.74072235994946],
[-105.00020027160645, 39.74191033368865],
[-105.00071525573731, 39.74276830198601],
[-105.00097274780272, 39.74369225589818],
[-105.00097274780272, 39.74461619742136],
[-105.00123023986816, 39.74534214278395],
[-105.00183105468751, 39.74613407445653],
[-105.00432014465332, 39.74732195489861]
], [
[-105.00361204147337, 39.74354376414072],
[-105.00301122665405, 39.74278480127163],
[-105.00221729278564, 39.74316428375108],
[-105.00283956527711, 39.74390674342741],
[-105.00361204147337, 39.74354376414072]
]
], [
[
[-105.00942707061768, 39.73989736613708],
[-105.00942707061768, 39.73910536278566],
[-105.00685214996338, 39.73923736397631],
[-105.00384807586671, 39.73910536278566],
[-105.00174522399902, 39.73903936209552],
[-105.00041484832764, 39.73910536278566],
[-105.00041484832764, 39.73979836621592],
[-105.00535011291504, 39.73986436617916],
[-105.00942707061768, 39.73989736613708]
]
]
]
}
};
var coorsField = {
"type": "Feature",
"properties": {
"popupContent": "Coors Field"
},
"geometry": {
"type": "Point",
"coordinates": [-104.99404191970824, 39.756213909328125]
}
};
Result:

JavaScript GeoJson Parser

i have geojson data:
{
"type":"FeatureCollection",
"metadata":{
"generated":1417015873000,
11-26T14:33:40&endtime=2014-11-26T14:33:45",
"title":"USGS Earthquakes",
"status":200,
"api":"1.0.13",
"count":1
},
"features":
[{
"type":"Feature",
"properties":
{
"mag":6.8,
"place":"160km NW of Kota Ternate, Indonesia",
"time":1417012423350,"updated":1417015584000,
"tz":480,
"url":"http://comcat.cr.usgs.gov/earthquakes/eventpage/usb000t08w",
"detail":"http://comcat.cr.usgs.gov/fdsnws/event/1/query?eventid=usb000t08w&format=geojson",
"felt":1,
"cdi":5,
"mmi":4.98,
"alert":"green",
"status":"reviewed",
"tsunami":1,
"sig":712,
"net":"us",
"code":"b000t08w",
"ids":",at00nfnhsd,pt14330000,usb000t08w,",
"sources":",at,pt,us,",
"types":",cap,dyfi,general-link,geoserve,impact-link,losspager,moment-tensor,nearby-cities,origin,phase-data,shakemap,tectonic-summary,",
"nst":null,
"dmin":1.45,
"rms":1.32,
"gap":37,
"magType":"mwb",
"type":"earthquake",
"title":"M 6.8 - 160km NW of Kota Ternate, Indonesia"
},
"geometry":{"type":"Point","coordinates":[126.5456,1.9752,41.06]},
"id":"usb000t08w"
}]
}
how to parse value "title" ?
var geojson = JSON.parse(geojson_data);
Turns the geojson string into an object, from there you can get whatever you values you want from it.
Edit: your json is invalid, where are you getting the data from? I cleaned it up, so you can call JSON.parse on it. However, it is not valid geojson, so I'd double check where you come up with the data. This geojson validator might help.
{
"metadata": {
"generated": 1417015873000,
"11-26T14: 33: 40&endtime=2014-11-26T14: 33": 45,
"title": "USGSEarthquakes",
"status": 200,
"api": "1.0.13",
"count": 1
},
"features": [
{
"type": "Feature",
"properties": {
"mag": 6.8,
"place": "160km NW of Kota Ternate, Indonesia",
"time": 1417012423350,
"updated": 1417015584000,
"tz": 480,
"url": "http://comcat.cr.usgs.gov/earthquakes/eventpage/usb000t08w",
"detail": "http://comcat.cr.usgs.gov/fdsnws/event/1/query?eventid=usb000t08w&format=geojson",
"felt": 1,
"cdi": 5,
"mmi": 4.98,
"alert": "green",
"status": "reviewed",
"tsunami": 1,
"sig": 712,
"net": "us",
"code": "b000t08w",
"ids": ",at00nfnhsd,pt14330000,usb000t08w,",
"sources": ",at,pt,us,",
"types": ",cap,dyfi,general-link,geoserve,impact-link,losspager,moment-tensor,nearby-cities,origin,phase-data,shakemap,tectonic-summary,",
"nst": null,
"dmin": 1.45,
"rms": 1.32,
"gap": 37,
"magType": "mwb",
"type": "earthquake",
"title": "M 6.8 - 160km NW of Kota Ternate, Indonesia"
},
"geometry": {
"type": "Point",
"coordinates": [
126.5456,
1.9752,
41.06
]
},
"id": "usb000t08w"
}
]
}

Categories