jsonpowerbipowerbi-desktopvegadeneb

limiting text mark in deneb/vega to be within another mark


consider this example (here with more sample data in the vega editor)

{
  "$schema": "https://vega.github.io/schema/vega-lite/v6.json",
  "data": {
    "name": "dataset",
    "values": [
    {
        "JobBeg": "2023-01-01T11:04:45",
        "JobEnd": "2023-01-01T18:04:45",
        "JobNum": "JN000",
        "Assigned_To": "David",
        "Midpoint": "2023-01-01T14:34:45"
    },
    {
        "JobBeg": "2023-01-01T15:07:31",
        "JobEnd": "2023-01-01T18:07:31",
        "JobNum": "JN001",
        "Assigned_To": "Bob",
        "Midpoint": "2023-01-01T16:37:31"
    }
]    
  },
  "layer": [
    {
      "mark": {"type":"bar", "stroke":"black","strokeWidth":2},
      "encoding": {
        "y": {
          "field": "Assigned_To",
          "type": "nominal",
          "title": "Assigned To"
        },
        "x": {
          "field": "JobBeg",
          "type": "temporal",
          "title": "Start Time",
          "axis":
          {
            "interval": "day",
            "step": 1
          }
        },
        "x2": {
          "field": "JobEnd",
          "title": "End Time"
        },
      "tooltip": [
        {
          "field": "JobBeg",
          "type": "temporal",
          "title": "Start Time",
          "format": "%Y-%m-%d %H:%M"
        },
        {
          "field": "JobEnd",
          "type": "temporal",
          "title": "End Time",
          "format": "%Y-%m-%d %H:%M"
        },
        {
          "field": "JobNum",
          "type": "nominal"
        }
      ]
      }
    },
    {
      "mark": {
        "type": "text",
        "align": "center",
        "baseline": "middle"
      },
      "encoding": {
        "y": {
          "field": "Assigned_To",
          "type": "nominal"
        },
        "x": {
          "field": "Midpoint",
          "type": "temporal"
        },
        "text": {
          "field": "JobNum",
          "type": "nominal"
        }
      }
    }
  ]
}

currently I am using the midpoint of a job beg/end to center the text mark in each bar, but I can't figure out a way to constrain the text mark to the size of the bar (ie if a very short duration I shouldn't see the text spill out of the bar)


Solution

  • One avenue to explore is to set the text mark's limit property via an expression to match the measured distance of JobEnd - JobBeg, which would truncate with an ellipsis if this length were exceeded, e.g.:

    {
      ...
        {
          "mark": {
            "type": "text",
            "align": "center",
            "baseline": "middle",
            "limit": {
              "expr": "scale('x', datum['JobEnd']) - scale('x', datum['JobBeg'])"
            }
          },
          ...
        }
      ...
    }
    

    Vega Editor (lines 116-118)

    You could also use this method to set the opacity of a mark or other similar property if you didn't want to see it, instead of truncating it.

    The other challenge here is that some mark positions overlap irrespective of this approach and still cause rendering artifacts, which can still be seen in the linked example. You may need to devise an avoidance technique, such as calculating a different baseline value to offset them (or, more drastically, consider using Vega and the label transform).