Search code examples
colorslegendvega-lite

Legend colors based on dynamic Lables


I have such a problem that I made custom labels, but also want to make them custom colored. When declaring in colors {scale: {domain:... range:...}} I cannot use my custom labels and whatever in domain despite there is filter it will show in the legend.

As an example without custom labels it looks like this: Image1. Here B3 is unnecessarily appears. What I want to achieve is this one Image2 where I can change colors of B1 for example to red, B2 to green, also B3 to yellow but it should appear only in correct filter. If I will apply range {scale: {range:...}} colors will not be assigned to particular category rather it will randomly allocate them.

Vega-lite code: Code

How it can be done? Image


Solution

  • One solution is to create a "fake" legend using a new spec and using the hconcat view composition. If you update the date filter you will see additional legend items appear.

    Please test this example to see if it solves your issue and remember to mark the case as closed.

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "data": {
        "values": [
          {
            "id": "123",
            "a": "Wed, 09 Aug 2023 06:00:00 GMT",
            "b": "Wed, 09 Aug 2023 17:00:23 GMT",
            "c": "A1",
            "d": "B1",
            "start_time": "Sat, 30 Dec 1899 06:00:00 GMT",
            "Date": "Wed, 09 Aug 2023"
          },
          {
            "id": "124",
            "a": "Wed, 09 Aug 2023 10:00:00 GMT",
            "b": "Wed, 09 Aug 2023 18:02:31 GMT",
            "c": "A2",
            "d": "B2",
            "start_time": "Sat, 30 Dec 1899 14:00:00 GMT",
            "Date": "Wed, 09 Aug 2023"
          },
          {
            "id": "125",
            "a": "Wed, 09 Aug 2023 19:01:07 GMT",
            "b": "Wed, 09 Aug 2023 22:01:17 GMT",
            "c": "A1",
            "d": "B2",
            "start_time": "Sat, 30 Dec 1899 22:00:00 GMT",
            "Date": "Wed, 09 Aug 2023"
          },
          {
            "id": "126",
            "a": "Wed, 07 Aug 2023 06:00:00 GMT",
            "b": "Wed, 07 Aug 2023 17:00:23 GMT",
            "c": "A4",
            "d": "B3",
            "start_time": "Sat, 30 Dec 1899 06:00:00 GMT",
            "Date": "Wed, 07 Aug 2023"
          }
        ]
      },
      "transform": [
        {
          "filter": {
            "field": "Date",
            "range": [
              {"year": 2023, "month": "Aug", "date": 8},
              {"year": 2023, "month": "Aug", "date": 10}
            ]
          }
        },
        {
          "groupby": ["d"],
          "window": [{"op": "count", "field": "id", "as": "count_id"}],
          "sort": [{"field": "d"}]
        },
        {"calculate": "datum.count_id + 'x: ' + datum['d']", "as": "grouping"}
      ],
      "spacing": 5,
      "hconcat": [
        {
          "encoding": {
            "y": {
              "field": "c",
              "type": "ordinal",
              "title": null,
              "axis": {"labelColor": "black"}
            }
          },
          "layer": [
            {
              "params": [
                {
                  "name": "highlight",
                  "select": {"type": "point", "on": "mouseover"}
                },
                {
                  "name": "opicomp",
                  "select": {"type": "point", "fields": ["d"]},
                  "bind": "legend"
                }
              ],
              "mark": {"type": "bar", "stroke": "black"},
              "encoding": {
                "x": {
                  "field": "a",
                  "type": "temporal",
                  "axis": {
                    "labelExpr": "datum.label",
                    "labelColor": "black",
                    "grid": true,
                    "gridDash": [5.5],
                    "gridColor": "grey",
                    "zindex": 1,
                    "orient": "bottom",
                    "format": "%H:%M:%S"
                  },
                  "title": "Time/Duration"
                },
                "x2": {"field": "b"},
                "color": {
                  "condition": [
                    {"test": "datum.d == 'B1'", "value": "red"},
                    {"test": "datum.d == 'B2'", "value": "blue"},
                    {"test": "datum.d == 'B3'", "value": "green"}
                  ],
                  "legend": null
                },
                "strokeWidth": {
                  "condition": [{"param": "highlight", "empty": false, "value": 1}],
                  "value": 0
                },
                "opacity": {
                  "condition": [
                    {
                      "test": {"field": "__selected__", "equal": "off"},
                      "value": 0.5
                    },
                    {"param": "opicomp", "value": 1}
                  ],
                  "value": 0.5
                },
                "tooltip": [
                  {
                    "field": "a",
                    "title": "Start",
                    "type": "temporal",
                    "format": "%d-%b-%y %H:%M"
                  },
                  {
                    "field": "b",
                    "title": "End",
                    "type": "temporal",
                    "format": "%d-%b-%y %H:%M"
                  }
                ]
              }
            },
            {
              "mark": {"type": "tick", "stroke": "black"},
              "encoding": {
                "x": {
                  "field": "Date",
                  "type": "temporal",
                  "title": null,
                  "axis": {
                    "labelColor": "black",
                    "grid": true,
                    "gridDash": [5.5],
                    "zindex": 1,
                    "orient": "top",
                    "format": "%d-%b-%y",
                    "labelExpr": "hours(datum['value']) == 0 ? datum['label'] : ''"
                  }
                }
              }
            }
          ]
        },
        {
          "layer": [
            {
              "params": [
                {
                  "name": "highlight",
                  "select": {"type": "point", "on": "mouseover"}
                }
              ],
              "mark": {"type": "square", "stroke": "black", "size": 100},
              "encoding": {
                "y": {
                  "field": "grouping",
                  "title": null,
                  "axis": {
                    "grid": false,
                    "domain": false,
                    "ticks": false,
                    "orient": "right"
                  },
                  "sort": {"field": "d", "order": "ascending"}
                },
                "color": {
                  "condition": [
                    {"test": "datum.d == 'B1'", "value": "red"},
                    {"test": "datum.d == 'B2'", "value": "blue"},
                    {"test": "datum.d == 'B3'", "value": "green"}
                  ],
                  "legend": null
                },
                "strokeWidth": {
                  "condition": [{"param": "highlight", "empty": false, "value": 1}],
                  "value": 0
                }
              }
            }
          ]
        }
      ],
      "config": {"axis": {"titleColor": "black"}, "view": {"stroke": "transparent"}}
    }
    

    enter image description here