Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Control canvas size with altair / vega-lite / vega-embed

I'm building graphs using vega-lite, and rendering them within a DOM using vega-embed. I love the tools and the abstractions, but I'm still figuring out how some of them work.

I'm working on an application where controlling the exact size of the canvas is important. Unfortunately, when I specify (for example)

bars = alt.Chart(df).mark_bar().encode(
  x='bins:O',
  y="weights:Q"
).properties(width=240, height=200)

I get a chart object that looks like this:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v2.6.0.json",
  "config": {
    "view": {
      "height": 300,
      "width": 400
    }
  },
  "data": {
    "name": "data-a681d02fb484e64eadd9721b37015d5b"
  },
  "datasets": {
    "data-a681d02fb484e64eadd9721b37015d5b": [
      {
        "bins": 3.7,
        "weights": 5.555555555555555
      },
      {
        "bins": 10.8,
        "weights": 3.439153439153439
      },
      {
        "bins": 17.9,
        "weights": 17.857142857142858
      },
      {
        "bins": 25.0,
        "weights": 24.206349206349206
      },
      {
        "bins": 32.0,
        "weights": 16.137566137566136
      },
      {
        "bins": 39.1,
        "weights": 12.3015873015873
      },
      {
        "bins": 46.2,
        "weights": 9.788359788359788
      },
      {
        "bins": 53.3,
        "weights": 5.423280423280423
      },
      {
        "bins": 60.4,
        "weights": 3.439153439153439
      },
      {
        "bins": 67.5,
        "weights": 1.8518518518518516
      }
    ]
  },
  "encoding": {
    "x": {
      "field": "bins",
      "type": "ordinal"
    },
    "y": {
      "field": "weights",
      "type": "quantitative"
    }
  },
  "height": 200,
  "mark": "bar",
  "width": 240
}

(Note the different height and width in config.view.)

I'm rendering to HTML like this:

<div id="my_id"></div>
<script>
const vlSpec = my_chart_obj;
vegaEmbed('#my_id', vlSpec, {
    actions: false
}).then(result=>console.log(result)).catch(console.warn);
</script>

This produces:

<div id="my-id" class="vega-embed">
  <canvas width="284" height="252" class="marks"></canvas>
  <div class="vega-bindings"></div>
</div>

Note: width="284" height="252"

It looks like width and height are being padded, but I can't figure out why or how.

The graph itself looks lovely, except that it's the wrong size and messes up my layout as a result.

enter image description here

Help!

like image 300
Abe Avatar asked Oct 24 '25 04:10

Abe


1 Answers

The width and height in config.view are set by Altair's default theme, and have no effect on the chart you created above, because they are overridden by the chart-level width and height properties.

If you would feel better removing this config from your chart, you can run

alt.themes.enable('none')

to clear the default chart theme (alt.themes.enable('default') will restore the default).


Regarding the size of the canvas: the chart width and heightproperties by default control the size of the chart panel itself, not including additional padding for axis labels and titles. If you want the entire canvas to fit in the specified bounds, including label padding, you can specify this via the autosize property; for example:

alt.Chart(df).mark_bar().encode(
  x='bins:O',
  y="weights:Q"
).properties(
    width=240,
    height=200,
    autosize=alt.AutoSizeParams(
        type='fit',
        contains='padding'
    )
)

enter image description here

But be aware that this will not work for every chart type; see Autosize Limitations for more information.

like image 197
jakevdp Avatar answered Oct 25 '25 18:10

jakevdp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!