jsonchartsvisualizationvega

Add Labels to Circular Pie/Gauge Chart


I have a config to draw multiple gauges chart in Vega charts.

I want to draw the text with values on top of each line that represents current value. The text should show value number and symbol "%" in the end. The end result needs to be similar to the chart on this enter image description here


Solution

  • enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "width": 400,
      "height": 600,
      "signals": [
        {"name": "centerX", "update": "width / 2"},
        {"name": "centerY", "update": "height / 2"},
        {"name": "radiusRef", "update": "min(width / 2, height / 2)"},
        {"name": "padding", "value": 18},
        {"name": "numArcs", "value": 2},
        {"name": "arcStep", "update": "0.4 / numArcs"},
        {"name": "ticksNumber", "value": 6},
        {"name": "ticksColor", "value": "#000000"},
        {"name": "showTicks", "value": true},
        {"name": "arc1", "value": {"value": 70, "fillColor": "#77A7FB"}},
        {"name": "arc2", "value": {"value": 40, "fillColor": "#FFB677"}},
        {"name": "innerRadius1", "update": "radiusRef + padding"},
        {"name": "outerRadius1", "update": "radiusRef * (1 - arcStep) - padding"},
        {"name": "minValue", "value": 0},
        {"name": "maxValue", "value": 100},
        {"name": "fontFactor", "update": "(radiusRef / 5) / 25"},
        {"name": "backgroundColor", "value": "#cbd1d6"},
        {"name": "fillColor3", "value": "#77FF77"}
      ],
      "data": [
        {
          "name": "ticks",
          "transform": [
            {
              "type": "sequence",
              "as": "data",
              "start": {"signal": "0"},
              "stop": {"signal": "(maxValue - minValue) + 0.1"},
              "step": {"signal": "(maxValue - minValue) / (ticksNumber - 1)"}
            },
            {"type": "formula", "expr": "datum.data + minValue", "as": "data_2"},
            {
              "type": "formula",
              "as": "radianRef",
              "expr": "PI * (datum.data / (maxValue - minValue))"
            },
            {
              "type": "formula",
              "as": "x",
              "expr": "centerX - ((outerRadius1 - (outerRadius1 - innerRadius1) * 0.6) * cos(datum.radianRef))"
            },
            {
              "type": "formula",
              "as": "y",
              "expr": "centerY - ((outerRadius1 - (outerRadius1 - innerRadius1) * 0.7) * sin(datum.radianRef))"
            }
          ]
        },
        {
          "name": "mainValues",
          "values": [
            {"name": "Policy 1", "value": 27},
            {"name": "Policy 2", "value": 75}
          ],
          "transform": [{"type": "window", "ops": ["row_number"], "as": ["index"]}]
        }
      ],
      "scales": [
        {
          "name": "gaugeScale",
          "type": "linear",
          "domain": {"data": "ticks", "field": "data_2"},
          "zero": false,
          "range": {"signal": "[-PI / 2, PI / 2]"}
        },
        {
          "name": "color",
          "type": "ordinal",
          "domain": {"data": "mainValues", "field": "name"},
          "range": {"scheme": "category10"}
        }
      ],
      "marks": [
        {
          "type": "arc",
          "name": "gauge3",
          "from": {"data": "mainValues"},
          "encode": {
            "enter": {
              "x": {"signal": "centerX"},
              "y": {"signal": "centerY"},
              "startAngle": {"signal": "-PI / 2"},
              "endAngle": {"signal": "PI / 2"},
              "outerRadius": {
                "signal": "radiusRef * (1 - datum.index * arcStep) - padding"
              },
              "innerRadius": {
                "signal": "radiusRef * (1 - datum.index * arcStep) + padding"
              },
              "fill": {"signal": "backgroundColor"}
            }
          }
        },
        {
          "type": "arc",
          "from": {"data": "mainValues"},
          "encode": {
            "enter": {"startAngle": {"signal": "-PI / 2"}},
            "update": {
              "x": {"signal": "centerX"},
              "y": {"signal": "centerY"},
              "innerRadius": {
                "signal": "radiusRef * (1 - datum.index * arcStep) + padding"
              },
              "outerRadius": {
                "signal": "radiusRef * (1 - datum.index * arcStep) - padding"
              },
              "endAngle": {"scale": "gaugeScale", "field": "value"},
              "fill": {"scale": "color", "field": "name"}
            }
          }
        },
        {
          "type": "arc",
          "from": {"data": "mainValues"},
          "encode": {
            "enter": {"startAngle": {"signal": "-PI / 2"}},
            "update": {
              "x": {"signal": "centerX"},
              "y": {"signal": "centerY"},
              "innerRadius": {
                "signal": "radiusRef * (1 - datum.index * arcStep) + padding"
              },
              "outerRadius": {
                "signal": "radiusRef * (1 - (datum.index - 1) * arcStep) + datum.index * 15"
              },
              "startAngle": {"scale": "gaugeScale", "signal": "datum.value - 0.3"},
              "endAngle": {"scale": "gaugeScale", "field": "value"},
              "fill": {"scale": "color", "field": "name"}
            }
          }
        },
        {
          "type": "text",
          "from": {"data": "mainValues"},
          "encode": {
            "update": {
              "radius": {
                "signal": "radiusRef * (1 - (datum.index - 1) * arcStep) + datum.index * 15"
              },
              "x": {"signal": "width", "mult": 0.5},
              "y": {"signal": "height", "mult": 0.5},
              "text": {"signal": "datum.value"},
              "align": {"value": "center"},
              "baseline": {"value": "middle"},
              "fill": {"scale": "color", "field": "name"},
              "dy": {"value": -8},
              
              "theta": {"signal": "scale('gaugeScale', datum.value)"}
            }
          }
        }
      ]
    }