Denys
Denys

Reputation: 333

Vega lite Geographic chart: does zoom on mouse scroll feature exist?

I am using this map https://vega.github.io/vega-lite/examples/geo_layer.html and I'm wondering if there is a zoom function in principle here? Found nothing in docs.

Upvotes: 2

Views: 213

Answers (2)

APB Reports
APB Reports

Reputation: 2451

You can try the following vega-lite spec. Here I apply params/signals to control zooming and panning. Use your mouse wheel to scroll in/out. Click and hold to pan. Dynamic colors per state and dynamic size of airports as we zoom in and out. We must use the mercator projection type for panning. If you only want a specific country then we could easily add a filter to limit based on long/lat etc

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "width": 800,
  "height": 600,
  "padding": 15,
  "autosize": "fit",
  "params": [
    {"name": "tx", "update": "width / 2"},
    {"name": "ty", "update": "height / 2"},
    {
      "name": "scale",
      "value": 300,
      "on": [
        {
          "events": {"type": "wheel", "consume": true},
          "update": "clamp(scale * pow(1.003, -event.deltaY * pow(16, event.deltaMode)), 150, 50000)"
        }
      ]
    },
    {
      "name": "angles",
      "value": [0, 0],
      "on": [{"events": "pointerdown", "update": "[rotateX, centerY]"}]
    },
    {
      "name": "cloned",
      "value": null,
      "on": [{"events": "pointerdown", "update": "copy('projection')"}]
    },
    {
      "name": "start",
      "value": null,
      "on": [{"events": "pointerdown", "update": "invert(cloned, xy())"}]
    },
    {
      "name": "drag",
      "value": null,
      "on": [
        {
          "events": "[pointerdown, window:pointerup] > window:pointermove",
          "update": "invert(cloned, xy())"
        }
      ]
    },
    {
      "name": "delta",
      "value": null,
      "on": [
        {
          "events": {"signal": "drag"},
          "update": "[drag[0] - start[0], start[1] - drag[1]]"
        }
      ]
    },
    {
      "name": "rotateX",
      "value": -240,
      "on": [{"events": {"signal": "delta"}, "update": "angles[0] + delta[0]"}]
    },
    {
      "name": "centerY",
      "value": 40,
      "on": [
        {
          "events": {"signal": "delta"},
          "update": "clamp(angles[1] + delta[1], -60, 60)"
        }
      ]
    }
  ],
  "layer": [
    {
      "data": {
        "url": "data/us-10m.json",
        "format": {"type": "topojson", "feature": "states"}
      },
      "projection": {
        "type": "mercator",
        "scale": {"signal": "scale"},
        "rotate": [{"signal": "rotateX"}, 0, 0],
        "center": [0, {"signal": "centerY"}],
        "translate": [{"signal": "tx"}, {"signal": "ty"}]
      },
      "mark": {"type": "geoshape", "fill": "lightgray", "stroke": "white"}
    },
    {
      "transform": [
        {"calculate": "scale", "as": "scale"},
        {"calculate": "round(scale/25)", "as": "size"}
      ],
      "data": {"url": "data/airports.csv"},
      "projection": {
        "type": "mercator",
        "scale": {"signal": "scale"},
        "rotate": [{"signal": "rotateX"}, 0, 0],
        "center": [0, {"signal": "centerY"}],
        "translate": [{"signal": "tx"}, {"signal": "ty"}]
      },
      "mark": {"type": "circle", "size": {"expr": "datum.size"}},
      "encoding": {
        "longitude": {"field": "longitude", "type": "quantitative"},
        "latitude": {"field": "latitude", "type": "quantitative"},
        "color": {"field": "state", "legend": false},
        "tooltip": [
          {"field": "name", "type": "nominal"},
          {"field": "city", "type": "nominal"},
          {"field": "state", "type": "nominal"}
        ]
      }
    }
  ],
  "config": {}
}

You can play with the colors by adding a transform for sort then adjust the color setup with a theme and sort etc.

"transform": [
        {"calculate": "scale", "as": "scale"},
        {"calculate": "round(scale/25)", "as": "size"},
        {"calculate": "(datum.longitude * datum.latitude)* -1", "as": "sort"}
      ],
    ....


        "color": {"field": "state", "type": "ordinal","legend": false, "sort":{"field": "sort","order": "descending"},"scale": {"scheme": "blueorange"}},

Happy charting!

Adam (APB Reports)

Upvotes: 0

davidebacci
davidebacci

Reputation: 30304

You can zoom the map manually by changing the scale factor of the projection as below. To actually bind this to mouse scroll is not currently supported as far as I'm aware. There is an open issue here you can rad about: https://github.com/vega/vega-lite/issues/3306

If I were you, I'd just use Vega and there is already an example here: https://vega.github.io/vega/examples/zoomable-world-map/

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

  "layer": [
    {
      "data": {
        "url": "data/us-10m.json",
        "format": {
          "type": "topojson",
          "feature": "states"
        }
      },
      "projection": {
        "type": "albersUsa", "scale":300
      },
      "mark": {
        "type": "geoshape",
        "fill": "lightgray",
        "stroke": "white"
      }
    },
    {
      "data": {
        "url": "data/airports.csv"
      },
      "projection": {
        "type": "albersUsa", "scale":300
      },
      "mark": "circle",
      "encoding": {
        "longitude": {
          "field": "longitude",
          "type": "quantitative"
        },
        "latitude": {
          "field": "latitude",
          "type": "quantitative"
        },
        "size": {"value": 10},
        "color": {"value": "steelblue"}
      }
    }
  ]
}

Upvotes: 1

Related Questions