I am trying to display multiple circles on a mapbox-gl map. The color of the circles depends on the value of the aqi property. I have set interpolation of the color depending on that value. The problem is I am always getting black circles.
The circle color property:
'circle-color': [
'interpolate',
['linear'],
['get', 'aqi'],
0,
'#eee695',
50,
'#a5fc03',
100,
'#dbfc03',
200,
'#fc1c03'
],
The full function:
map.on('load', () => {
Axios.get('https://api.waqi.info/map/bounds/?latlng=41.03143,20.52421,42.20194,22.89056&token='+AQI_KEY).then(res=>{
const data = [];
res.data.data.map(station=>{
if(station.aqi!=='-'){
data.push(JSON.stringify({ "type": "Feature", "properties": {"aqi": station.aqi},
"geometry":
{
"type": "Point", "coordinates": [ station.lon, station.lat ]
}
}))
}
})
map.addSource('AQI', {
'type': 'geojson',
'data':
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "aqi": "aqi" } },
"features": data.map(JSON.parse)
}
});
map.addLayer(
{
'id': 'AQI-heat',
'type': 'circle',
'source': 'AQI',
'paint': {
'circle-radius': {
'type': 'exponential',
'stops': [[0, 70], [500, 70]]
},
'circle-opacity': {
'type': 'exponential',
'stops': [[-99, 0.0], [-50, 1.0]]
},
'circle-color': [
'interpolate',
['linear'],
['get', 'aqi'],
0,
'#eee695',
50,
'#a5fc03',
100,
'#dbfc03',
200,
'#fc1c03'
],
'circle-blur': 1
}
}
);
})
})
}
Even tho I have set different colors for different values, I always just get black circles.
Related
I have MapBox with Voronoi diagrams and I want to color each polygon based on cluster it belongs to.
Here is my JSFiddle:
https://jsfiddle.net/re12chwa/2/
I tried to use Case but it doesn't work.
"fill-color": [
"case",
['==', ['get', "Cluster"], "31N"], "#00ffff",
['==', ['get', "Cluster"], "32"], "#ff00ff",
['==', ['get', "Cluster"], "33"], "#0000ff",
['==', ['get', "Cluster"], "34"], "#ffff00",
['==', ['get', "Cluster"], "35"], "#00ff00",
'#ea0a8e '
]
{
type: "Feature",
properties: {
Site: "zahod",
Cluster: "31N",
"": ""
},
geometry: {
type: "Point",
coordinates: [16.552992, 43.521409]
}
Any help will be great.
There is no IDs in voronoiPolygons, so the layer won't recognize them (it prints default color "#ea0a8e").
Solution for this is adding IDs to voronoiPolygons as property from points.
for (i = 0; i < voronoiPolygons["features"].length; i++) {
voronoiPolygons["features"][i].properties = { "id": points["features"][i]["properties"]["Cluster"] }
}
And filling color by getting id.
"fill-color": [
"case",
["==", ["get", "id"], "31N"], "#00ffff",
["==", ["get", "id"], "32"], "#ff00ff",
["==", ["get", "id"], "33"], "#0000ff",
["==", ["get", "id"], "34"], "#ffff00",
["==", ["get", "id"], "35"], "#00ff00",
"#ea0a8e"
]
Here is working example:
https://jsfiddle.net/0k7sw9fc/
I'm using MapBox GL JS v1.4.1
Based on the example here: https://docs.mapbox.com/mapbox-gl-js/example/cluster/
I cannot get my cluster count to display.
I have tried replicating the MapBox example directly and also using my own data but whatever I try results in the count not displaying.
This is what I have:
<div id="map"></div>
mapboxgl.accessToken = 'ACCESS_TOKEN';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v10',
zoom: 1
});
My geoJson data:
var geoData = {
"type": 'FeatureCollection',
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [151.12100, -33.78420]
},
"properties": {
"title" : "title",
"description": "description"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [151.12100, -33.78420]
},
"properties": {
"title" : "title",
"description": "description"
}
}
]
};
Loading the map, adding geoJSON, clusters etc:
map.on('load', function() {
map.addSource("testMapData", {
type: "geojson",
data: geoData,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
map.addLayer({
id: "cluster-count",
type: "symbol",
source: "testMapData",
filter: ["has", "point_count"],
layout: {
"text-field": "{point_count_abbreviated}",
"text-font": ["Arial Unicode MS Bold"],
"text-size": 12,
"text-allow-overlap" : true
}
});
map.addLayer({
id: "clusters",
type: "circle",
source: "testMapData",
filter: ["has", "point_count"],
paint: {
"circle-color": "#f1f075",
"circle-radius": 40
}
});
map.addLayer({
id: "unclustered-point",
type: "circle",
source: "testMapData",
filter: ["!", ["has", "point_count"]],
paint: {
"circle-color": "#51bbd6",
"circle-radius": 8,
"circle-stroke-width": 1,
"circle-stroke-color": "#fff"
}
});
});
Based on the above I should get the cluster count on each of my clusters, but I only see the cluster with no count.
The console also shows no errors.
I can't determine if there's an issue with my geoJSON (it validates via the linter here: http://geojsonlint.com/)... or if the issue lies in how I have added the cluster-count layer... or somewhere else entirely.
Currently you are adding the cluster-count layer before the clusters layer so the latter is covering up the former. If you switch the order you will see both: https:///codepen.io/pj_leonard/pen/bGGgYwv?editors=1000
Update your code to the following:
map.on('load', function() {
map.addSource("testMapData", {
type: "geojson",
data: geoData,
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
map.addLayer({
id: "clusters",
type: "circle",
source: "testMapData",
filter: ["has", "point_count"],
paint: {
"circle-color": "#f1f075",
"circle-radius": 40
}
});
map.addLayer({
id: "cluster-count",
type: "symbol",
source: "testMapData",
filter: ["has", "point_count"],
layout: {
"text-field": "{point_count_abbreviated}",
"text-font": ["Arial Unicode MS Bold"],
"text-size": 12,
"text-allow-overlap" : true
}
});
map.addLayer({
id: "unclustered-point",
type: "circle",
source: "testMapData",
filter: ["!", ["has", "point_count"]],
paint: {
"circle-color": "#51bbd6",
"circle-radius": 8,
"circle-stroke-width": 1,
"circle-stroke-color": "#fff"
}
});
});
Disclaimer: I work at Mapbox
If the order of the layers is correct, pay attention to text font, eg: "text-font": ["MicrosoftYaHeiRegular"]
I'm trying to dynamically replace series data and plot bands in my Highcharts gauge. So far I've managed to dynamically change the series data, however I am stuck struggling to replace the bands. This is what I've tried:
let highchartsChartOptions = {
"chart": {
"type": "gauge",
"renderTo": "chart"
},
"series": [{
"data": [247600]
}],
"yAxis": {
"plotBands": [{
"from": 156700,
"to": 277150,
"color": "#ff0000",
}, {
"from": 277150,
"to": 386100,
"color": "#00ff00"
}],
"min": 100000,
"max": 400000
},
"pane": {
"background": null,
"startAngle": -90,
"endAngle": 90
}
};
let seriesData = [
[226800],
[247600]
];
let seriesBands = [
[{
"from": 156700,
"to": 277150,
"color": "#ff0000",
}, {
"from": 277150,
"to": 386100,
"color": "#00ff00"
}],
[{
from: 100000,
to: 250000,
"color": "#ff0000"
}, {
from: 250000,
to: 400000,
"thickness": 15,
}]
];
const replacePlotBand = (axis, id, replacement) => {
axis.removePlotBand(id);
axis.addPlotBand(replacement);
};
let chart = new Highcharts.Chart(highchartsChartOptions);
let flip = true;
$("#change").on("click", () => {
chart.series[0].setData(seriesData[flip ? 0 : 1]);
chart.xAxis[0].update({
plotBands: seriesBands[flip ? 0 : 1]
});
chart.redraw(true);
flip = !flip;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script src="https://code.highcharts.com/highcharts-more.src.js"></script>
<div id='chart' style="width: 800px; height: 500px;"></div>
<button id="change">Change data</button>
My intention is to replace both series data and plot bands with a different set of data but right now only the series data seems to be updated.
I'm not sure what I am doing wrong here.
I have also tried adding IDs to the bands and doing:
chart.xAxis[0].removePlotBand('band1');
chart.xAxis[0].removePlotBand('band2');
chart.xAxis[0].addPlotBand(seriesBands[flip ? 0 : 1][0]);
chart.xAxis[0].addPlotBand(seriesBands[flip ? 0 : 1][1]);
but that also did not work (see fiddle https://jsfiddle.net/yc2gnp7x/2/).
Your highChartOptions uses yAxis but you are removing and adding to xAxis
I am trying to use Mapbox/Turfjs to understand how many points are in a polygon. I have rendered my polygon and points in map.onload Is then possible to call Turf.js from another function AFTER the polygon and points have been rendered to the map?
Something like this...?
$(document).ready(function(){
mapboxgl.accessToken = 'eeeeeeeeee';
map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [ 32.62939453125,1.7355743631421197],
zoom: 6.5,
pitch: 40,
maxZoom: 17
});
map.on('load', function () {
//geofence data
map.addSource('fencedata', {
type: 'geojson',
data: 'data/fence.geojson'
});
map.addLayer({
id: 'fence',
type: 'fill',
"source": "fencedata",
'layout': {},
'paint': {
'fill-color': '#FF0000',
'fill-opacity': 0.3
}
});
//points data
map.addSource("pointdata", {
type: "geojson",
data: 'data/points.geojson',
cluster: true,
clusterRadius: 20
});
map.addLayer({
"id": "points",
"type": "circle",
"source": "pointdata",
"paint": {
'circle-color': 'rgba(255, 255, 46, 1.0)',
'circle-radius': 8
}
});
});
map.addControl(new mapboxgl.NavigationControl());
});
geofence();
function geofence(){
var ptsWithin = turf.within(points, fence);
}
You have your points as GeoJSON, and your polygon as GeoJSON - so, yes, you can use TurfJS to find out which points are within the polygon. It looks like the code you've proposed is correct. The fact you're using Mapbox is irrelevant to this particular task.
If you're experiencing a problem with this approach, indicate it in your question.
Try to add the geofence() function inside the map on-load function after adding those layers, By that way you can make sure that the geofence() function is called after the layers have been loaded
map.on('load', function () {
//geofence data
map.addSource('fencedata', {
type: 'geojson',
data: 'data/fence.geojson'
});
map.addLayer({
id: 'fence',
type: 'fill',
"source": "fencedata",
'layout': {},
'paint': {
'fill-color': '#FF0000',
'fill-opacity': 0.3
}
});
//points data
map.addSource("pointdata", {
type: "geojson",
data: 'data/points.geojson',
cluster: true,
clusterRadius: 20
});
map.addLayer({
"id": "points",
"type": "circle",
"source": "pointdata",
"paint": {
'circle-color': 'rgba(255, 255, 46, 1.0)',
'circle-radius': 8
}
});
geofence();
});
map.addControl(new mapboxgl.NavigationControl());
});
function geofence() {
var ptsWithin = turf.within(points, fence);
}
I am looking function which enable me to loss of parts of Layer when zooming the map.
map.on('zoomend', onZoomend)
function onZoomend(feature){
if(map.getZoom()<11)
{map.addLayer("road_2"==feature.properties.density)};
if(map.getZoom()>11)
{map.removeLayer("road_2"==feature.properties.density)};
}
My GeoJson file is in panel layers:
var overLayers = [
{
group: "Layer",
collapsed: true,
layers: [
{
name: "Road",
icon: iconByName('fuel_road'),
layer: L.geoJson(road,{style: style_road})
},
File GeoJson bulid that:
var road = {
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "density" : "road_1"....
{ "type": "Feature", "properties": { "density" : "road_2"....
{ "type": "Feature", "properties": ....
Update:
Is this way have a future? What must it be improved?
function style_road(feature) {
if ("road_1" == feature.properties.density) {
return {
weight: 3,
opacity:function()
{if (zoom > 13) {opacity:0},
else (zoom < 13) {opacity:1},
},
color: 'red',
};
}
else if ("road_2" == feature.properties.density){
return {
weight: 1.5,
opacity: 1,
color: 'red',
};
}
else {
return {
weight: 0.5,
opacity: 1,
color: 'red',
};
}
}
I am not sure if I understand you right, but you want to remove a layer when zooming in and adding it when zooming out?
You just can use:
if(map.getZoom()<11){
mylayer.removeFrom(map);
}else{
mylayer.addTo(map);
}
Did I understand you right?
UPDATE:
You can iterate through the GeoJson Layer and set the fillOpacity to 0 for hiding some geoms:
var geoJsonLayer = L.geoJson(myGeoJson).addTo(map);
if(map.getZoom()<11){
geoJsonLayer.eachLayer(function(layer) {
if(layer.feature.properties.density == "road_"){
layer.setStyle({fillOpacity:0});
}
});
}