heatmap.js
heatmap.js copied to clipboard
Smart adjustment for gradient configuration
I'm trying to find some way to adjusting the heatmap configuration based on the data so that it is meaningful in more cases. I'm using this for a mapping application. I've gotten part of the way by nudging the color stops depending on zoom level, but it's still not as useful as I'd like.
I have a map showing crash data. Depending on the query, there could be anywhere from 0 - 5000 locations on the map with widely varying density. Here are some pictures:
Useful, hand tweaked color stops:
Less useful, automatic zoom-based color stops (use local maximum is on):
Automatic doing a better job with fewer points:
Certainly I could refine my zoom-based color stop adjustment, but it would be better if I could get the maximum density and curve the gradient based on that number, even if that had to be an iterative process. This would allow the heatmap to be meaningful no matter the data put in. The heatmap configuration would be data aware. Is there a way to get the maximum density or maximum color for a heatmap? Has anyone successfully made a data-aware heatmap configurator?
Just for reference, my current color stop scaling formula is:
var stops = [0, 0.4, 0.5, 0.6, 0.7, 0.8, 0.89, 0.99],
colors = ["rgba(0,0,0,0)",
"rgba(50,200,100,0.01)",
"rgba(50,200,200, 0.5)",
"rgba(0,255,0, 0.55)",
"rgba(155,255,0, 0.6)",
"rgba(255,255,0, 0.65)",
"rgba(255,155,0, 0.7)",
"rgba(255,0,0,0.7)"];
var f = zoom - 7; // 8 is my "default" zoom level
$.each(stops, function (i, v) {
var s = Math.max(Math.min(v - f*(-4 * Math.pow(v-0.5, 2) + 1)/10, 1), 0);
config.gradient[s] = colors[i];
});
Thanks!
Hi. Do you use a different radius for each point of your dataset? (ie: [lat, lng, value, radius])
@LePew No, they are all the same.
@jocooler It's just a hint, but you could try adjusting minOpacity to 0.1 (for low values) ?
For my own needs (using leaflet-heatmap), I modified the "scaleRadius" from scale = Math.pow(2, zoom);
to scale=zoom;
because I need to scaleRadius when I zoom in, but the default value wasn't really useful to me.
If your dataset's values are something else than 0 or 1, you could also index the radius of each point to the value, so the gradient would be smaller for small values.
Here's a sample with minOpacity set to 0.8, same radius for each point, point value=1:
And another one with minOpacity set to 0.01, same radius for each point, point value=1:
@jocooler have you tried using the onExtremaChange
callback configuration?
It will be called whenever min or max changes, simply pass the callback to your instance config:
var cfg = {
..
onExtremaChange: function(extremaData) {
// extremaData contains
// { min: <number>, max: <number>, gradient: <current gradient cfg> }
}
};