mapbox / mapbox/mapbox-gl-js

cameraForBounds is not accounting for an asymmetrical padding in the camera center result (regression in v3.3.0 to v3.4.0)

Open
#13,645 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug :lady_beetle:
Dominant language
TypeScript
Stars
12.4k
Forks
2.4k
PR merge metrics
No merged PRs in 30d

Description

### mapbox-gl-js version

v3.4.0 through to v3.20.0 present this issue, however it was working in v3.3.0, so possibly a regression caused by #13126

### Browser and version

_No response_

### Expected behavior

`cameraForBounds` will return a `center` and `zoom` required to fit the map to a given bounds, accounting for an optional padding. However when using an asymmetrical padding, for example `left: 500, right: 0` it is expected that the resulting camera `center` would be more offset to account.

For example compare the resulting camera center in the two cases below, while the camera zoom changes to account for the padding, the center does not, but it should, resulting in the camera not respecting the padding.

```js
map.cameraForBounds(bounds, {
left: 500,
right: 0,
top: 0,
bottom: 0
}).center

map.cameraForBounds(bounds, {
left: 0,
right: 0,
top: 0,
bottom: 0
}).center
```

### Actual behavior

In v3.3.0 this was the case, but from v3.4.0 onwards adding `padding` to the `cameraForBounds` options affects the resulting camera `zoom`, but not the resulting camera `center`.

### Link to the demonstration

1. In v3.3.0 the following code produces this result, works as expected.

```js
const camera = map.cameraForBounds(bounds, {
padding: {
top: 10,
right: 10,
bottom: 10,
left: 10 + 400
}
});
map.easeTo({
center: camera.center,
zoom: camera.zoom,
bearing: camera.bearing
});
```
Image

2. In v3.4.0, the same code produces this result, doesn't work as expected.

Image

4. To obtain the same result as v3.3.0 when using v3.4.0 and later one needs to add an offset, like this

```js
const camera = map.cameraForBounds(bounds, {
padding: {
top: 10,
right: 10,
bottom: 10,
left: 10 + 400
},
offset: [ 400 / 2, 0 ]
});
map.easeTo({
center: camera.center,
zoom: camera.zoom,
bearing: camera.bearing
});
```

This is just a workaround, as you're applying an offset to correct it, but really an offset should offset it further.

Image

full example, compare across v3.3.0 and v3.4.0

# full example
```html




Display a map on a webpage




body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
#panel { position: absolute; top: 0; bottom: 0; width: 400px; background: rgba(0, 0, 255, 0.2);}






mapboxgl.accessToken = 'pk.ey...';

const bounds = [-71.08482, 43.08003225358635, -66.96466, 47.44777598732787 ];
const polygon = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-71.08482, 43.08003225358635],
[-66.96466, 43.08003225358635],
[-66.96466, 47.44777598732787],
[-71.08482, 47.44777598732787],
[-71.08482, 43.08003225358635]
]
]
}
};

const map = new mapboxgl.Map({
container: 'map',
devtools: true,
style: 'mapbox://styles/mapbox/streets-v9',
center: [-68.13734351262877, 45.137451890638886],
zoom: 5,
hash: false,
});

map.on('load', function() {
map.addLayer({
'id': 'bounds',
'type': 'line',
'source': {
'type': 'geojson',
'data': polygon
},
'layout': {},
'paint': {
'line-color': 'red',
'line-width': 2
}
});

const camera = map.cameraForBounds(bounds, {
padding: {
top: 10,
right: 10,
bottom: 10,
left: 10 + 400
},
// a workaround in 3.4.0 and later
//offset: [400 / 2, 0]
});

map.easeTo({
center: camera.center,
zoom: camera.zoom,
bearing: camera.bearing
});

});




```

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 at the cameraForBounds entry point and reproduce the supplied bounds and asymmetric-padding example across v3.3.0 and v3.4.0. Investigate how padding and offset affect the returned center, then add a regression test showing that the center accounts for asymmetric padding while the bounds still fit.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
api, frontend, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.