Make pins in symbol layer pixel perfect for clicking - javascript

I am using layer of symbols and want to make it possible as much as possible pixel perfect the icon be. How i can achieve this i am using custom maki icons for these symbols.
Is it somehow possible to increase the size of the icon but reduce the size of square for example?
Ive tried to play with size and paddings in the layer setup but this did not help.
My Layer looks like this:
"id": tableName + "-layer",
"type": "symbol",
"source": tableName,
"source-layer": tableName,
"layout": {
"icon-image": 'marker-15-svg',
"icon-size": ["interpolate",
["linear"], ["zoom"],
4, 1.3,
8, 1.5,
13, 2.5
],
"icon-allow-overlap": true,
"icon-padding": 0,
"icon-offset": [0, -3],
"icon-anchor": "center",
"symbol-z-order": "source"
},
"paint": {
"icon-color": materialSetColor,
"icon-opacity": {"stops": [[10, 0.7], [30, 1]]},
}

Related

Mapbox GL JS: Clustering circle not rendered properly upon zooming out

I am building a website that renders circles on a map. If the ["feature-state", "value] property is >= 1, the circle is green and if the ["feature-state", "value"] property is 0 or null, the circle is red (the default value is 0). When my map is zoomed in enough, the circles are rendered properly (all circles with ["feature-state", "value] >= 1 are rendered green). However, when I zoom out, the cluster circle that contains children features/circles with a ["feature-state", "value], the circle is rendered as red instead of green. Is there any way to ensure that the clusters are rendered as green if the sum of their children's ["feature-state", "value] is >= 1?
Below is my rendering code:
map.addSource('cities', {
"type": "geojson",
"data": "cities.geojson",
"cluster": true,
"clusterMaxZoom": 14,
"clusterRadius": 80
});
map.addLayer({
"id": "cities",
"type": "circle",
"source": "cities",
"paint": {
"circle-color": [
"case",
["==", ["feature-state", "value"], null], "#ff4d4d",
[">=", ["feature-state", "value"], 1], "#33cc33",
"#ff4d4d"
],
"circle-radius": [
"case",
["==", ["feature-state", "value"], null], 9,
[">=", ["feature-state", "value"], 1], 12,
6
],
"circle-opacity" : [
"case",
["==", ["feature-state", "value"], null], 0.7,
[">=", ["feature-state", "value"], 1], 1,
0.7
]
},
});
Below is how I set the "feature-state":
map.setFeatureState({source: "cities", id : 124312}, {value: 1});
Here is a screenshot of the map when correctly zoomed in:
Here is a screenshot of the map when zoomed out (the red circle in the area marked with a white marker should be rendered green):
This can be done with clusterProperties option of the source object which takes custom expression to aggregate properties for a cluster point.
Note: clusterProperties option does not support feature-state aggregation and can only work with properties. I'll explain it in steps below and there's also a codepen example attached at bottom.
First, define an expression that aggregates feature's properties that form a cluster.
{
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 80,
clusterProperties: {
/*
get the property numUser, then cast it to number or 0,
then sum it, then store the sum as cluster's numUser property
*/
numUsers: ["+", ["number", ["get", "numUsers"], 0]]
},
type: "geojson",
data: geojson,
}
Update style expressions to use feature properties instead of feature-state:
paint: {
"circle-color": [
"case",
["==", ["get", "numUsers"], null], "#ff4d4d",
[">=", ["get", "numUsers"], 1], "#33cc33",
"#ff4d4d"
],
"circle-radius": [
"case",
["==", ["get", "numUsers"], null], 9,
[">=", ["get", "numUsers"], 1], 12,
6
],
"circle-opacity": [
"case",
["==", ["get", "numUsers"], null], 0.7,
[">=", ["get", "numUsers"], 1], 1,
0.7
]
}
Update GeoJSON properties:
// Update after 2 seconds
setTimeout(() => {
const newGeojson = {
...geojson,
features: geojson.features.map(feature => {
if ([0, 1].includes(feature.id)) { // update features selectively
feature.properties.numUsers = 1;
}
return feature;
})
};
map.getSource('geom').setData(newGeojson);
}, 2000);
Here's a working codepen: https://codepen.io/manishraj/full/wvwmNKR
There's a related example here, by mapbox: https://docs.mapbox.com/mapbox-gl-js/example/cluster-html/

amcharts adding legand with the dynamic text

I am using amcharts for rendering the data in column charts, I need the legand to be shown along with the text of the each 'valueField'.
I am trying something like this :
"legend": {"horizontalGap": 10,
"maxColumns": 1,
"position": "right",
"useGraphSettings": true,
"markerSize": 10,
"marginTop": 10,
"labelText":"[[value]]"
}
My JSFiddle
It's showing the different colors well, but the text is not getting displayed.
Any suggestions would be highly appreciable!
You need to set the title of the graphs so that the legend knows what to use to replace the labelText of each legend, which defaults to [[title]]:
https://docs.amcharts.com/3/javascriptcharts/AmLegend#labelText
It looks like the labelText will not parse any other special placeholders like [[value]] other than [[title]].
So the fix is, just to remove what you have set as the label text in the legend section (just leave it as default), and add titles on each graph:
legend: {
...,
// "labelText": "[[value]]"
},
...,
graphs: [
{
id: "g1",
fillAlphas: .9,
title: "value 1",
...
},
{
id: "g2",
fillAlphas: .9,
title: "OR WHATEVER YOU WANT TO DISPLAY",
...
},
...
]
fiddle: https://jsfiddle.net/davidliang2008/fm7jLkta/

Mapbox add background image on circle

I'm using mapbox and I've clustered my data. Now I want to show a
background image (instead of a black background!) when a user has zoomed to a point.
I add it like this:
this.map.addLayer({
id: "unclustered-point",
type: "circle",
source: "earthquakes",
filter: ["!has", "point_count"],
paint: {
"circle-color": "black",
"circle-radius": 8,
"circle-stroke-width": 4,
"circle-stroke-color": "#fff",
}
});
I'm loading my geojson like this:
this.map.addSource("earthquakes", {
type: "geojson",
data: this.locations,
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});
this.map.addLayer({
id: "clusters",
type: "circle",
source: "earthquakes",
filter: ["has", "point_count"],
paint: {
"circle-color": [
"step",
["get", "point_count"],
"#002e5b",
100,
"#002e5b",
750,
"#002e5b"
],
"circle-radius": [
"step",
["get", "point_count"],
20,
100,
30,
750,
40
],
}
});
So how can I get a background image instead of a black background?
You can add another layer of points with your custom image that becomes visible at z14. This way the custom image will cover the black circles.
I recommend making the black circle extremely small or nonexistent so it doesn't conflict with the custom images.

How to specify limit color for line chart

How to specify a different color for a line by specifying upper and lower limit in Amchart.
Please find below code for a line chart.
{
'id': 'g3',
"title": "Temperature",
'balloonText':'[[category]]<br><b><span style=\'font-size:14px;\'>[[value]]</span></b>',
'bullet': 'round',
'bulletSize': 8,
"lineColor": "#9524a3",
'lineThickness': 1,
'negativeLineColor': '#FF0000',
'type': 'smoothedLine',
"negativeBase":8,
'valueField':"temperature",
},
as I am able to set lower limit using negativeBase property.
How to set the upper limit?
While there isn't a positive base setting you can use a combination of negativeLineColor and lineColor to switch the graph color depending if its decreasing or increasing.
There is an example here:
https://codepen.io/team/amcharts/pen/155bbc984311730a95242f38c84f78d1
"graphs": [{
"useNegativeColorIfDown": true,
"lineColor": "#cddd00",
"negativeLineColor": "#ccb7dc",
The graph will be lineColor when increasing and negativeLineColor when decreasing.
https://docs.amcharts.com/3/javascriptcharts/AmGraph#useNegativeColorIfDown
https://docs.amcharts.com/3/javascriptcharts/AmGraph#negativeLineColor
OR
You can take color value from json and use lineColorField.
Please find below json and line graph object
{
"DeviceName": "1Device",
"Date": "2018-09-11 20:10:55",
"temperature": 10.00,
"Color temperature": "#ff3232",
"humidity": 10.00,
"Color humidity": "#17c723",
"co2": 10.00,
"Color co2": "#ff3232",
"airpressure": 10.00,
"Color airpressure": "#9bbd3b"
}
{
'id': "g"+i,
"title": data["Parameter"][i],
'balloonText':'[[category]]<br><b><span style=\'font-size:14px;\'>[[value]]</span></b>',
'bullet': 'round',
'bulletSize': 8,
"lineColor": data["Colors"][i],
// "legendColorField": "Color "+data["Parameter"][i],
"lineColorField": "Color "+data["Parameter"][i],
'lineThickness': 1,
// "negativeBase":5,
//'negativeLineColor': '#FF0000',
'type': 'smoothedLine',
'valueField': data["Parameter"][i],
}

Data-driven cluster colour with mapboxgl

I am trying to draw circle which colour depends on a "group" attribute in my geojson. I followed a simple example with these colours:
map.addSource("data", {
type: "geojson",
data: url,
cluster: true,
clusterMaxZoom: 12, // Max zoom to cluster points on
clusterRadius: 20 // Radius of each cluster when clustering points (defaults to 50)
});
map.addLayer({
'id': 'population',
'type': 'circle',
'source': 'data',
'paint': {
// make circles larger as the user zooms from z12 to z22
'circle-radius': {
'base': 1.75,
'stops': [[12, 2], [22, 180]]
},
// color circles by ethnicity, using a match expression
// https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-match
'circle-color': {
'property': 'group',
'type': 'categorical',
stops: [
['1', 'rgba(252,141,98,0.5)'],
['2', 'rgba(141,160,203,0.5)'],
['3', 'rgba(141,160,203,0.5)'],
['4', 'rgba(141,160,203,0.5)'],
['5', 'rgba(141,160,203,0.5)'],
['6', 'rgba(141,160,203,0.5)'],
//'4', '#3bb2d0',
/* other 'rgba(102,194,165,0.1)'*/
]
}
}
},'3d-buildings');
Now I would also like my clusters to follow some kind of colour-pattern. For instance, if the clusters contains a majority of group 1 then it does get the colour of group 1. Same for groupe 2 and so on.
But all I for the cluster points is black dots. I would very much like to know if there is a way to do better than that.
I have been following this example and updated it with the additional "type":"categorical" as required by the new versions of mapboxgl.
My data is a geojson that goes like this:
{"type": "FeatureCollection", "features": [{"id": 1, "type": "Feature", "properties": {"group":1}, "geometry": {"type": "Point", "coordinates": [17.8304903812012, 59.1886524824444]}}
Would anyone know how to achieve that with mapbox?
Edit:
Two images to show the problems that I currently have. The first image is basically my non-clustered visualization where you see two different colours based on the two groups.
The second image, is the clustered version, which only display black clusters. I would like for clusters with a majority of group 1 to be orange and for clusters with a majority of group 2 to be green.
Edit
Now I have also seen that I might have to do that with supercluster, but the only proper example that I have found is broken (stops working when we zoom too much and the points are always clustered). Also it seems that this is using old mapbox features that are now deprecated. Would someone know how to make this work easily on the provided example?

Categories