eurostat / gridviz

A package for visualizing gridded data 🌐
https://github.com/eurostat/gridviz
European Union Public License 1.2
194 stars 9 forks source link

Improve Square color WebGL legend documentation. #136

Open joewdavies opened 1 week ago

joewdavies commented 1 week ago

Trying to make a Square color WebGL Style map with a corresponding legend was a lot harder than it should be, in fact I had to give up!

There are no examples of this that I could find.

Here is my attempt, that doesnt work for a MultiResolutionDataset:

    //define style
    const styles = [
        new SquareColorWebGLStyle({
            filter: (c) => c[DATAFIELD] > 0,
            color: interpolateOrRd,
            tFun: (cell) => cell[DATAFIELD] / 1000000,
            stretching: { fun: 'log', alpha: -7 },
        }),
        new StrokeStyle({
            filter: (c) => c[DATAFIELD] > 0,
            strokeColorCol: DATAFIELD,
            strokeColor: (v) => (+v ? '#666' : ''),
            maxZoom: 80,
        }),
    ]

    //add legend
    styles[0].legends = [
        new ColorLegend({
            title: 'Number of inhabitants',
            width: 290,
            ticks: 3,
            colorScale: interpolateOrRd,
        }),
    ]
jgaffuri commented 1 week ago

You need to specify the color legend text, with the textScale parameter of the legend. This is a function [0,1] -> text which returns the tick text based on the position of the tick along the legend bar, specified within [0,1].

For a simple case, here https://github.com/eurostat/gridviz/blob/master/examples/legends/colorLegend.html it is straightfoward: The style color is specified as: color: (cell) => d3.interpolateYlOrRd(cell.population / 20000) And the legend label as an inverse function: textScale: (t) => t * 20000

For a case based on a viewscale, here: https://github.com/eurostat/gridviz/blob/master/examples/legends/colorLegendViewScale.html The style is defined based on a predefined viewscale viewScale: gridviz.viewScaleColor({ valueFunction: (c) => +c.TOT_P_2021, colorScale: d3.interpolateYlOrRd, stretching: gridviz.logarithmicScale(-7) }) And the legend label uses also the (predefined) viewscale inverse function: textScale: (t, vs) => vs?.invert(t)

For your case, no viewscale is used so what you need to do is to set this function: textScale: (t, vs) => ... so that it returns the label text corresponding to the tick position. For your case, since you use a stretching function (computed by the GPU), you need to apply the inverse of the stretching function { fun: 'log', alpha: -7 } which is exponential function. You can directly use what is provided in the utils/stretching.js file which provides for each stretching function its inverse.

Give it a try with:

//predefine this next to the webgl style
const scale = gridviz.logarithmicScale(-7)

//add this in the legend definition
(...)
textScale: (t) => 1000000 * scale.invert(t)

and let me know !

Not also on that example: https://github.com/eurostat/gridviz/blob/master/examples/legends/colorLegendText.html that it is possible to define the labels in a static way: textScale: (t) => t == 0 ? "Low" : t == "1" ? "High" : t == 0.5 ? "Middle" : "X" which could also be used for your case !

jgaffuri commented 1 week ago

Feel free to close the issue if it works !