Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pan and zoom for geoshape mark #3306

Open
kanitw opened this issue Jan 25, 2018 · 14 comments
Open

Support pan and zoom for geoshape mark #3306

kanitw opened this issue Jan 25, 2018 · 14 comments
Assignees

Comments

@kanitw
Copy link
Member

kanitw commented Jan 25, 2018

We need to create examples and comprehensively test different options for geo especially trying selection like interval on x/y positions.

@kanitw kanitw added this to the 2.x Maps milestone Jan 25, 2018
@kanitw kanitw changed the title Selection support for geo Interaction / Selection Support for geo Jan 26, 2018
@domoritz domoritz added the Geo label Feb 1, 2018
@kanitw kanitw changed the title Interaction / Selection Support for geo Test Interaction / Selection Support for geo Mar 11, 2018
@kanitw
Copy link
Member Author

kanitw commented Mar 22, 2018

Look like projection cannot be bind yet -- vega/altair#632 (comment)

@arvind
Copy link
Member

arvind commented Apr 5, 2019

@allenjlee: Here's the geo selection issue we discussed. I believe we support single/multi selections with geo projections already but a good first test would be to build out a few examples of each. The flight links example provides a nice base case that you can start adding some interesting interactivity to for both selection types. I'll let you ideate a little here yourself :)

Interval selections are the more trickier ones. As we discussed, these selection generate signals in visual space (vnames that record the x/y coordinates of the region dragged) which are converted to data coordinates (dnames) via scale inversion individually (i.e., visual_x -> scale_x.invert -> data_x; visual_y -> scale_y.invert -> data_y). This approach won't work with geo projections because they are bivariate (i.e., they manipulate both x/y together). In fact, there are some really weird projections out there.

Instead, we added a new intersect expression function in Vega v5 (see the changelog for documentation on its signature) to do bounding box hit testing for us (the function is implemented in the vega-functions package). For now, don't worry about what changes need to be made to the compiler. Instead, start by adding a simple 2D interval selection (i.e., {"type": "interval", "translate": false, "zoom": false}) and to highlight points selected in this example and update the generated Vega spec by modifying signals to use the intersect function instead of scale inversions and removing any unnecessary signals. Once you get that working, try reintroducing the translate and/or zoom properties to see how that changes your spec design. Try and get a good sense of how you think the output Vega spec should change for our next meeting :)

@mattijn
Copy link
Contributor

mattijn commented Apr 6, 2019

A while ago I saw this notebook https://observablehq.com/@jake-low/web-mercator-tile-visibility. It might be useful to get a feeling with these geo projected intervals. If not, just ignore.
ezgif com-resize

I think it is really a big achievement if you can make these interval selections work with geo projections in Vega(-Lite).

@ObservedObserver
Copy link
Contributor

In 2022, is there a recommended way to make zoomable vega-lite geo visualization?

@kaushiksrini
Copy link

@kanitw Are there any updates to this? I can see it's available in vega. I would be interested in giving it a shot to get it working in vega-lite.

@domoritz
Copy link
Member

Actually, it's available now. We can probably close this @kanitw?

@kaushiksrini
Copy link

@domoritz great! are there vega-lite examples with panning and zooming in maps/geo data?

@arvind
Copy link
Member

arvind commented Oct 23, 2023

Hi @kaushiksrini, #6953 contains a couple of examples (interactive_1d_geo_brush and interactive_airport_crossfilter). We're working one writing up this functionality in the documentation, and creating more examples.

For now, with PR #6953, intervals on maps are limited to brushing. Panning and zooming will be forthcoming in a future release.

@kaushiksrini
Copy link

Thanks @arvind, that sounds good! Is panning and zooming actively being worked on? I use altair and vega-lite for viz and this feature would be beneficial - would be happy to work on it and submit a PR.

@arvind
Copy link
Member

arvind commented Oct 23, 2023

Thanks @kaushiksrini. Panning & zooming isn't something we're actively working on yet—so it would be something we'd very much welcome a PR on.

#6953 walks through the changes made to support intervals on geo—we'd need to extend these changes to src/compile/selection/translate.ts and src/compile/selection/zoom.ts. I imagine we'd be able to use most if not all of the existing signal infrastructure these two files generate, but then we'd need to feed the resultant output to the center0, center, and scale properties of Vega projections.

I'd be happy to find time to jump on a Zoom call if this is something you'd be interested in contributing to!

@kaushiksrini
Copy link

@arvind Thanks, I would be interested in submitting a PR for this feature.

I will look through the resources you provided and get a grasp of the repo and the functionalities. I shall reach out to schedule a Zoom call to learn more after that. Thanks again!

@joelostblom
Copy link
Contributor

Thanks for you interest in helping out with this feature @kaushiksrini! I think it would be highly valuable to be able to pan and zoom maps in VL, especially as support for tile-based maps is also being explored in #8885. Since this is a feature I'm excited about, I just wanted to check in if you were able to get started on it with the tips above from Arvind?

@kaushiksrini
Copy link

@joelostblom Hey! I look forward to making my first altair contribution. I was looking at it and trying to understand it, but didn't reach out to Arvind yet. Have some time and am planning to pick this up again. @arvind would you be available to hop on a Zoom call in the coming couple of weeks?

@joelostblom joelostblom changed the title Test Interaction / Selection Support for geo Support pan and zoom for geoshap marks Apr 12, 2024
@joelostblom joelostblom changed the title Support pan and zoom for geoshap marks Support pan and zoom for geoshape mark Apr 12, 2024
@apb-reports
Copy link

Here is a vega-lite example for any people interested. 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 it seems? If you only want a specific country then we could easily add a filter to limit based on long/lat etc

visualization

{
  "$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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Geospatial visualization
Development

No branches or pull requests

9 participants