Mapbox JS Runtime Styling from collection - mapbox

So I have a Mapbox Tileset I've uploaded with census-block information for the US. Each geometry in the tileset has a property called GeoID, that I am trying to apply a style to based on another collection I have.
The collection is an array objects with this format: [{geoid: string, weight: number}, {geoid: string, weight: number},...]
I want to match the GeoIDs from the array to the layer from the tileset and color it based on the corresponding weight property from that object. Weight is a number between 0 and 1. I have tried searching the documentation on runtime styling and expressions from Mapbox, but I can't find anything about extrapolating data from a collection and conditionally applying it to the right geometries from a tileset.

You can generate an expression from your list of weights and than pass it to the layer your want to style:
const weights = [
{geoid: 1, weight: 10},
{geoid: 2, weight: 5},
{geoid: 3, weight: 30},
];
const cases = weights.map(weight => {
const condition = ['==', ['get', 'geoid'], weight.geoid];
const output = getColor(weight.weight);
return [
condition,
output
];
});
const expresion = ['case',
...cases.reduce((flat, conditionAndOutput) => [...flat, ...conditionAndOutput]),
'<default-color>'
];
/*
Will result in:
[
"case",
[
"==",
[
"get",
"geoid"
],
1
],
"rgb(255, 255, 255)",
[
"==",
[
"get",
"geoid"
],
2
],
"rgb(255, 255, 255)",
[
"==",
[
"get",
"geoid"
],
3
],
"rgb(255, 255, 255)",
"<default-color>"
]
*/

Related

Customize default colors for multi dataset in Doughnut Chart ng2-charts in Angular 14

Angular 14, ChartJS: 4.1.1, NG2-Charts: 4.1.1. I am facing some trouble when trying to customize doughnut chart colors. Here I tried setting colors individually for each datasets, but its not working as expected. And without setting any colors, it working fine with default colors.
this.doughnutChartData = {
labels: this.doughnutChartLabels = [ 'Label1', 'Label2', 'Label3','Label4' ],
datasets: [
{ data: this. doughnutChartAircraftDatasets,backgroundColor: [
'#fc5858'
] },
{ data: this.doughnutChartChartBagDatasets, backgroundColor: [
'#19d863'
]},
{ data: this.doughnutChartChartFlightDatasets, backgroundColor: [
'#fdf57d'
]},
{ data: this.doughnutChartChartPassengerDatasets, backgroundColor: [
'#fdbb7d'
]}
]
};
Any help on this appreciated !
Thanks in advance.
you can set background color of any chart like this.
type: 'doughnut',
data : {
datasets: [
{
label:[ 'label1', 'label2', 'label3' ],
data: [ 350, 450, 100 ],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)',
'#ffC0CB'
],
},
]
},
The ng2-charts library works with the original chartjs one. The docs for the last one are really big, but you can find everything you want there.
The way you change the colors is like this:
const data = {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)'
],
hoverOffset: 4
}]
};
So you don't have to set the color for each dataset, instead, you have to set an array of colors in the desired property, in your case, backgroundColor.
Here is the doc for the doughnut and pie charts.

Sync map and graph series in apache echarts

I am using Apache Echarts v5, and I am trying to implement a graph with a world map background.
For this, I understand the best choice is to use a "graph" serie and a "map" serie, both reading from a "geo" configuration, based in a geoJSON or the world map, which I downloaded from here. Yet I am having a hard time figuring how to do this two things:
Sync coordinates, so the elements of the graph are always in the correct places of the map.
Be able to zoom in are out both the graph and the map at the same time.
For this I have prepared a minimal example of what I am doing. This code can be directly pasted into any echarts online example and it should work (I used other geoJson for mockup).
myChart.showLoading();
$.get(ROOT_PATH + '/data/asset/geo/HK.json', function (geoJson) {
myChart.hideLoading();
echarts.registerMap('fullMap', geoJson);
myChart.setOption(
option = {
legend: {
data: [
{
name: 'One',
},
{
name: 'Two',
},
{
name: 'Three',
},
],
bottom: '25',
itemHeight: '10',
textStyle: {
fontSize: '10',
},
type: 'scroll',
},
geo: [
{
map: 'fullMap',
layoutSize: '100%',
geoIndex: 0,
},
],
series: [
{
type: 'graph',
layout: 'none',
roam: true,
lineStyle: {
color: 'source',
curveness: 1e-21,
},
data: [
{
id: 'A',
name: 'A',
category: 0,
x: 51.8954823121139,
y: 0.918566971127893,
symbol: 'rect',
},
{
id: 'B',
name: 'B',
category: 0,
x: 52.0742496381072,
y: 1.22603740005249,
symbol: 'rect',
},
{
id: 'C',
name: 'C',
category: 0,
x: 52.8723466202309,
y: -0.192814484661784,
symbol: 'rect',
},
{
id: 'D',
name: 'D',
category: 0,
x: 53.3688011059499,
y: 0.0024000083847046,
symbol: 'rect',
},
],
links: [
{
source: 'A',
target: 'B',
},
{
source: 'B',
target: 'C',
},
],
categories: [
{
name: 'One',
},
{
name: 'Two',
},
{
name: 'Three',
},
],
},
{
map: 'fullMap',
type: 'map',
left: 0,
top: 0,
right: 0,
bottom: 0,
boundingCoords: [
[-180, 90],
[180, -90],
],
geoIndex: 0
},
],
})
});
The thing is, if I try to set the "coordinateSystem" for the graph serie to "geo", the graph stops rendering, and currently the zoom only works for the graph, not the map. Moreover, I have set my map to follow coordinates with "boundingCoords", but I do not see that same setting in the graph serie.
The documentation is not very clear about this, so any help would be appreciated.

Apache echarts scatter: assign label to each point

I am building an echarts scatter graph that contains 6 points. I would like to manually assign a label to each point, like I did with the label of X and Y axis.
Is there a way to achieve this? I searched in Apache Echarts docs but I did not find any useful setting for assigning a label to "data" values.
Here is the source code of my graph:
option = {
xAxis: {
data: ['Low', 'Med', 'High'],
name: "Value",
},
yAxis: {
min: '5',
name: "Score",
},
series: [
{
type: 'scatter',
symbolSize: 20,
data: [
[2,9.8],
[1,8.8],
[2,5.9],
[1,9.8],
[1,10.0],
[3,9.8],
[2,10.0],
[1,9.8],
[2,5.9],
[1,9.8]
],
label: {
show: true,
position: 'right',
color: "black",
fontSize: 16,
},
}
],
grid:{
show: true,
backgroundColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgb(255, 102, 102)'
},
{
offset: 1,
color: 'rgb(153, 255, 153)'
}])
},
};
You could specify the labels as an additional value in the data array:
data: [
[ 2, 9.8, "label1" ],
[ 1, 8.8, "label2" ],
...
Then use a formatter function in your label definition, to select the third element of the data array as the label:
label: {
...
formatter: function(d) {
return d.data[2];
}
I also found this solution, working as well as Chris one:
series: [
{
type: 'scatter',
symbolSize: 15,
data: [
{value: [2,9.8] , name: 'value1'},
{value: [1,8.8] , name: 'value2'},
{value: [2,5.9] , name: 'value3'},
],
label: {
show: true,
position: 'right',
formatter: params => params.name,
color: "black",
fontSize: 16,
},

Mapbox - achieving three states of paint opacity

I am trying to have 3 states of opacity for the following situation:
Clicked = Opacity: 0.8
Hover = Opacity: 0.6
Default = Opacity: 0.4
I have this code so far:
'paint': {
'fill-color': '#627BC1',
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
0.6,
0.4
]
}
However given it's boolean, can someone help me understand how I can make this into an array with three states rather than 2?
Here is a useable example:
https://codepen.io/hiven/pen/NWwBXJj
James
You should be able to do something like the following
paint: {
"fill-color": "#627BC1",
"fill-opacity": [
"case",
["==", ["feature-state", "mystate"], 1],
0.6,
["==", ["feature-state", "mystate"], 2],
0.8,
0.4
]
}
Then you would just set "mystate" as required...
// Hover
map.setFeatureState(
{ source: "states", id: clickedStateId },
{ mystate: 1 }
);
// Clicked
map.setFeatureState(
{ source: "states", id: clickedStateId },
{ mystate: 2 }
);
With the default being 0.4
This way you can support an arbitrary number states, each with their own value - rather than a simple Boolean "true/false"

How to add polygon properly in leaflet.js

When using leaflet.js to render polygon.
The following examples have different results.
Example 1
const map = L.map('map', {
preferCanvas: true,
zoomControl: false,
attributionControl: false
});
const latlngs = [
[
6,
5
],
[
7,
1
],
[
9,
2
]
];
const polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
map.fitBounds(polygon.getBounds());
Example 2
...
const latlngs = [
[
116,
115
],
[
117,
111
],
[
119,
112
]
];
const polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
map.fitBounds(polygon.getBounds());
Why is that?
And what can I do if I have to set latlngs data like Example 2.
The reason is that Leaflet uses latitude and longitude by default and projects it on a plane using a Web Mercator projection. On your second polygon, the coordinates are out of bounds for latitude.
If you just need to draw a triangle in "pixel" coordinates, you can use CRS.Simple.
const map = L.map('map', {
preferCanvas: true,
zoomControl: false,
attributionControl: false,
// Add this line:
crs: L.CRS.Simple
});
See JSFiddle: http://jsfiddle.net/ekqvwo76/