FrugalTPH
FrugalTPH

Reputation: 573

Render different fill/stroke colours depending on positive/negative x-axis value

I'm trying to code a little chart for use in risk/opportunity analysis. You feed in 4 values:

And it visualises those with charts as follows:

Risk / Opportunity Analysis Glyphs

The shaded fill renders the Pre values, whilst the stroke renders the Post values. Geometry in the left quadrant represents risk and should be red, whilst geometry in the right quadrant represents opportunity and should be green.

I'm struggling to find out how to check for negative consequence values and assign colour accordingly. I think it'll be done in the last two lines of my code below:

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 500,
  "height": 250,

  "data": [
    {
      "name": "table",
      "values": [
        {"C": -4,  "L": 0, "f":"Pre"}, {"C": 0,  "L": 4, "f":"Pre"}, 
        {"C": 0,  "L": 2, "f":"Post"}, {"C": -1,  "L": 0, "f":"Post"}
      ]
    }
  ],

  "scales": [
    {
      "name": "xscale",
      "type": "linear",
      "range": "width",
      "nice": true,
      "zero": true,
      "domain": {"data": "table", "field": "C"},
      "domainMax": 4,
      "domainMin": -4
    },
    {
      "name": "yscale",
      "type": "linear",
      "range": "height",
      "domain": {"data": "table", "field": "L"},
      "domainMax": 4,
      "domainMin": 0
    },
    {
      "name": "color",
      "type": "ordinal",
      "range":"ordinal",
      "domain": {"data": "table", "field": "f"}
    }
  ],

  "axes": [
    {"orient": "bottom", "scale": "xscale", "tickCount": 10 },
    {"orient": "left", "scale": "yscale", "tickCount": 5, "offset": -250 }
  ],

  "marks": [
    {
      "type": "group",
      "from": {
        "facet": {
          "name": "series",
          "data": "table",
          "groupby": "f"
        }
      },
    "marks": [
    {
      "type": "area",
      "from": {"data": "series"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "C" },
          "y": {"scale": "yscale", "field": "L"},
          "y2": {"scale": "yscale", "value": 0 }, 
          "fillOpacity": [{ "test": "indata('series', 'f', 'Pre')", "value": 0.3 }, {"value": 0}],
          "strokeWidth": [{ "test": "indata('series', 'f', 'Pre')", "value": 0 }, {"value": 2}],
          "fill": [{ "test": "indata('series', 'f', 'Pre')", "value": "red" }, {"value": "red"}],
          "stroke": [{ "test": "indata('series', 'f', 'Pre')", "value": "red" }, {"value": "red"}]
        }        
      }
    }
  ]
    }
  ]
}

Can anyone give me some pointers as to how to test the data values & set fill & stroke colours accordingly?

Thanks

Upvotes: 1

Views: 73

Answers (1)

codex
codex

Reputation: 702

Vega signals can be used to conditionally paint colors based on data values.

In the given vega spec, changing the fill property like this should do what you are expecting if data has Positive quadrant C values also.

          "fill": { "signal": "datum.C > 0 ? 'green': 'red'"},

Upvotes: 1

Related Questions