mapbox / mapbox/mapbox-gl-js

Map-independent projection/unprojection

Open
#5,687 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

api :memo: feature :green_apple:
Dominant language
TypeScript
Stars
12.4k
Forks
2.4k
PR merge metrics
No merged PRs in 30d

Description

This is opened in response to [this comment](https://github.com/mapbox/mapbox-gl-js/pull/5662#issuecomment-344646887) on PR #5662, suggesting I open an issue to discuss this use case.

### My Use Case
I have a react app which uses a map to geographically filter lots of results which appear in a sidebar – think [Zillow-style navigation](https://www.zillow.com/homes/for_sale/globalrelevanceex_sort/32.952215,-116.83033,32.372422,-117.451058_rect/10_zm/).

As is the idiom of react and other compositional frameworks, data flows unidirectionaly from the outermost component down the heirarchy of children. My goal here is to be able to calculate a GeoJSON polygon that represents the visible region of the globe, independant of actually rendering the map component.

Given the center point (Lng/Lat), zoom, pitch, bearing (all of which are stored in the URL), and the screen resolution, I need to get a `LngLat` for a given `Point` on the screen.

It's important that it's seperate from the rendered map for a few reasons:

1. This needs to be calculated to populate the list during server side rendering, where we can't actually draw the map.
2. We need to calculate this in different places:
- API calls over-fetch (essentially using a smaller zoom)
- Client side filtering considers panels that cover part of the map
3. OCD and the fact that we've maintained unidirectional data flow elsewhere 😉

Of course, the resulting polygon must be identical to the field of view in the map itself. This would be trivial, except for pitch and bearing.

### Initial Design

My initial strategy was to use the same `Transform` class used internally by the map. This worked quite well in the browser, but my [PR to export it](https://github.com/mapbox/mapbox-gl-js/pull/5662#issuecomment-344646887) exposed more internals than was desired. Additionally, when I began using it server-side, its requirement for WebGL broke in our current SSR strategy.

Here's the kind of thing I would do using the `Transform` class:

```es6
const transform = new Transform();
transform.center = { lng: geoLongitude, lat: geoLatitude };
transform.bearing = geoBearing;
transform.pitch = geoPitch;
transform.resize(window.innerWidth, window.innerHeight);

// get bounds for a search query
transform.zoom = geoZoom - 1;
const nw = transform.pointLocation(new Point(0, 0)).toArray();
const ne = transform.pointLocation(new Point(window.innerWidth, 0)).toArray();
const se = transform.pointLocation(new Point(window.innerWidth, window.innerHeight)).toArray();
const sw = transform.pointLocation(new Point(0, window.innerHeight)).toArray();
const coordinates = [[nw, ne, se, sw, nw]];

// figure out the "visible" center, taking into consideration the list and panels
transform.zoom = geoZoom;
const [ visibleLongitude, visibleLatitude ] = transform.pointLocation(new Point((transform.width + 654) / 2, transform.height / 2)).toArray();

```

Is there any reasonable way to accomplish this without the heavy internals of `Transform`?

Thanks!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the Transform class and its pointLocation usage, along with PR #5662 and the linked comment, to understand the requested separation from map rendering and the WebGL dependency. Define how projection and unprojection should accept the center, zoom, pitch, bearing, viewport size, and screen points, then verify that the resulting polygon and offset-center calculations match the rendered map and work for server-side rendering.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
computer-graphics, frontend, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.