Signal with expression based on width not evaluated when first rendered

212 views
Skip to first unread message

Brian

unread,
Jul 22, 2016, 6:19:26 PM7/22/16
to vega-js
I'd like to adjust the amount of data shown on a chart based on the width of the chart.  On mobile devices I'd like to show less data rather than showing a large amount of data in a compressed space.

Below is a spec that reproduces the problem I am encountering.  It is a modified version of the "stocks" example.  I added a "filteredStocks" dataset that filters the data based on the "minYear" signal which uses the width signal, and moved some of the mark properties inside of an "update".  When the chart width is <= 250 then it will only show data from 2005 and greater.  Otherwise it will show everything since 2000.

This works when I resize the chart after it has been rendered using view.width(<new width>).update().

But my problem is that when the chart is first rendered the "minYear" signal is not being evaluated.  Instead the signal's "init" value is being used.

If you copy and paste the spec below into the Vega editor it will render with data starting from 2000 and the chart will be 500px wide.  In your console window, type "ved.view.width(250).update()" and it will correctly resize and filter the data to show only 2005 and greater.

However, if you change the spec to have "width: 250" and parse the spec, the "minYear" signal isn't evaluated to have the value "2005".  This causes the chart to show data starting from 2000.  If you resize the chart to 500 and back to 250 using the view API, then it updates the "minYear" signal and renders it correctly.

Is this just a bug?  Is there a way to force a signal to be evaluated when the chart is first being rendered? Or is there a better way to approach this?

Thanks.


{
  "width": 500,
  "height": 200,
  "signals": [{
    "name": "minYear",
    "init": 2000,
    "expr": "if(width <= 250, 2005, 2000)"
  }],
  "data": [
    {
      "name": "stocks",
      "url": "data/stocks.csv",
      "format": {"type": "csv", "parse": {"price":"number", "date":"date"}}
    }, {
      "name": "filteredStocks",
      "source": "stocks",
      "transform": [{
          "type": "filter",
          "test": "year(datum.date) >= minYear"
        }]
    }
  ],
  "scales": [
    {
      "name": "x",
      "type": "time",
      "range": "width",
      "domain": {"data": "filteredStocks", "field": "date"}
    },
    {
      "name": "y",
      "type": "linear",
      "range": "height",
      "nice": true,
      "domain": {"data": "filteredStocks", "field": "price"}
    },
    {
      "name": "color", 
      "type": "ordinal", 
      "domain": {"data": "filteredStocks", "field": "symbol"},
      "range": "category10"
    }
  ],
  "axes": [
    {"type": "x", "scale": "x", "tickSizeEnd": 0},
    {"type": "y", "scale": "y"}
  ],
  "marks": [
    {
      "type": "group",
      "from": {
        "data": "filteredStocks",
        "transform": [{
          "type": "facet", "groupby": ["symbol"] 
        }]
      },
      "marks": [
        {
          "type": "line",
          "properties": {
            "enter": {
              "stroke": {"scale": "color", "field": "symbol"},
              "strokeWidth": {"value": 2}
            }, "update": {
              "x": {"scale": "x", "field": "date"},
              "y": {"scale": "y", "field": "price"}
            }
          }
        },
        {
          "type": "text",
          "from": {
            "transform": [{"type": "filter", "test": "datum.date == 1267430400000"}]
          },
          "properties": {
            "enter": {
              "fill": {"scale": "color", "field": "symbol"},
              "text": {"field": "symbol"},
              "baseline": {"value": "middle"}
            }, "update": {
              "x": {"scale": "x", "field": "date", "offset": 2},
              "y": {"scale": "y", "field": "price"}
            }
          }
        }
      ]
    }
  ]
}

Roy I

unread,
Jul 25, 2016, 4:21:08 PM7/25/16
to vega-js
Hi Brian:  According to Vega documentation: "The initial value of the signal. If init is an object with an expr property, the expression is evaluated to produce the signal's initial value."


In your example, try:

  "signals": [{
    "name": "minYear",
    "init": {"expr": "if(width <= 250, 2005, 2000)"},
    "expr": "if(width <= 250, 2005, 2000)"
  }],

Cody Robinson

unread,
Sep 7, 2017, 1:42:48 PM9/7/17
to vega-js
Hey Roy, 

I'm curious if there is a way for the signal to gather the values from a data field rather than hardcoded like above? 

The case I am looking to solve is setting a threshold of when you can stop zooming from occurring: https://vega.github.io/vega-editor/?mode=vega&spec=panzoom_points

Specifically, I've tried to add 

    {
      "name": "xMax",
      "init": 22,
      "streams": [
        {
          "type": "mouseScroll",
          "expr": "min((xRange.max - anchor.x)*mouseScroll + anchor.x, 22)"
        }
      ]

However, the highlight value is currently hardcoded and I want to be able to change the data at runtime and have this value be linked to that data change.  

    {
      "name": "xMin-xMax-data",
      "values": [{"value": -5},{"value": 70}]
    },

Is this currently possible?

Thanks!

Arvind Satyanarayan

unread,
Sep 7, 2017, 2:18:22 PM9/7/17
to Cody Robinson, vega-js
Hi Cody,

Unfortunately, with Vega 2, it is not possible to reference data values within signal expression strings. If you're able to upgrade to Vega 3, the extent transform (https://vega.github.io/vega/docs/transforms/extent/) or data expression functions (https://vega.github.io/vega/docs/expressions/#data-functions) should give you what you need.

-Arvind
-----
Arvind Satyanarayan <http://arvindsatya.com/>

--
You received this message because you are subscribed to the Google Groups "vega-js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vega-js+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Cody Robinson

unread,
Sep 7, 2017, 3:06:49 PM9/7/17
to vega-js
Thanks Arvind. Unfortunately updating is an option right now, so we will just go with re-rendering the entire visuals rather than trying to update the data. 
To unsubscribe from this group and stop receiving emails from it, send an email to vega-js+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages