Vega-Lite Dynamic Label Width (Reactive Geometry)

56 views Asked by At

I am creating a timeline bar chart that has labels on the bars. Currently, the labels will go outside of the bar and overlap with others. I am looking to capture the width of a bar so I can use that for the label width limit to cut off anything outside of the bar.

enter image description here

Vega Code

I did find a possibly working solution on this site: https://forum.enterprisedna.co/t/deneb-limit-data-label-width/32850 enter image description here

Unfortunately the did not explain the full solution, and I've been unable to figure it out. I'm unsure what concat_0_x contains or how to reproduce it. I've tried the Vega documentation on scale and looking for usage examples but haven't been able to figure out a way to find the bar width.

If someone could help fill in the gaps from the above solution or provide another method of obtaining the bar width so I can use it as the width limit, it would be greatly appreciated.

1

There are 1 answers

3
davidebacci On BEST ANSWER

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      {
        "person": "Alice",
        "activity": "Traveling",
        "start": "2024-02-02T05:30:00",
        "end": "2024-02-02T06:30:00"
      },
      {
        "person": "Alice",
        "activity": "Working",
        "start": "2024-02-02T07:00:00",
        "end": "2024-02-02T12:00:00"
      },
      {
        "person": "Alice",
        "activity": "Lunch",
        "start": "2024-02-02T12:30:00",
        "end": "2024-02-02T13:00:00"
      },
      {
        "person": "Alice",
        "activity": "Breakdown",
        "start": "2024-02-02T14:00:00",
        "end": "2024-02-02T14:30:00"
      },
      {
        "person": "Bob",
        "activity": "Working",
        "start": "2024-02-02T06:00:00",
        "end": "2024-02-02T11:30:00"
      },
      {
        "person": "Bob",
        "activity": "Maintenance",
        "start": "2024-02-02T12:00:00",
        "end": "2024-02-02T13:30:00"
      },
      {
        "person": "Bob",
        "activity": "Pre-op",
        "start": "2024-02-02T14:00:00",
        "end": "2024-02-02T15:00:00"
      },
      {
        "person": "Charlie",
        "activity": "Working",
        "start": "2024-02-02T06:30:00",
        "end": "2024-02-02T11:00:00"
      },
      {
        "person": "Charlie",
        "activity": "Lunch",
        "start": "2024-02-02T11:30:00",
        "end": "2024-02-02T12:00:00"
      },
      {
        "person": "Charlie",
        "activity": "Breakdown",
        "start": "2024-02-02T14:30:00",
        "end": "2024-02-02T15:00:00"
      },
      {
        "person": "Alice",
        "activity": "Parked",
        "start": "2024-02-02T15:00:00",
        "end": "2024-02-02T17:00:00"
      },
      {
        "person": "Bob",
        "activity": "Parked",
        "start": "2024-02-02T15:00:00",
        "end": "2024-02-02T17:00:00"
      },
      {
        "person": "Charlie",
        "activity": "Parked",
        "start": "2024-02-02T15:00:00",
        "end": "2024-02-02T17:00:00"
      }
    ]
  },
  "layer": [
    {
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "field": "start",
          "type": "temporal",
          "axis": {"title": "Timeline"}
        },
        "x2": {"field": "end"},
        "y": {
          "field": "person",
          "type": "nominal",
          "axis": {"title": "Persons"}
        },
        "color": {
          "field": "activity",
          "type": "nominal",
          "scale": {
            "domain": [
              "Traveling",
              "Working",
              "Lunch",
              "Breakdown",
              "Maintenance",
              "Pre-op",
              "Parked"
            ],
            "range": [
              "#1f77b4",
              "#ff7f0e",
              "#2ca02c",
              "#d62728",
              "#9467bd",
              "#8c564b",
              "#e377c2"
            ]
          },
          "legend": null
        }
      }
    },
    {
      "transform": [
        {"calculate": "scale('layer_0_x', datum['end']) - scale('layer_0_x', datum['start'])", "as": "testLength"}
      ],
      "mark": {
        "type": "text",
        "align": "left",
        "dx": 3,
        "dy": 1,
        "baseline": "middle",
        "fontSize": 9,
        "limit": {"expr": "datum['testLength'] - 2"},
        "ellipsis": " ",
        "x": {"expr": "scale('layer_0_x',datum.start)"}
      },
      "encoding": {
        "text": {"field": "activity"},
        "y": {
          "field": "person",
          "type": "nominal",
          "axis": {"title": "Persons"}
        }
      }
    }
  ],
  "resolve": {"scale": {"x": "independent"}}
}