From 7eb5a4752e1db18122624e39d2dacff15d9421bf Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 17 Sep 2022 10:14:12 -0600 Subject: [PATCH 1/3] Don't overzoom when selecting a large POI Previously we zoomed to the "point" of any POI to a zoom level that seemed optimized for building-sized points. For large features, like an entire city, this meant zooming way in to some seemingly random part of the city. Now we prefer the bbox whenever available instead of the point. With this commit, zooming works reasonably for city-sized objects and the node-based POIs, which have no bbox such as: e.g. Overcast Coffee Company - "id": "node/4349270303", But some small venues are defined as an osm way, and thus have a Bbox. With this change we're now zooming a little too close (IMO). An example of a too-close zoom: e.g. Victrola Coffee Roasters - "id": "way/206623301" --- web/frontend/src/components/SearchBox.vue | 1 + web/frontend/src/pages/PlacePage.vue | 15 +++++++++++++-- web/frontend/src/utils/models.ts | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/web/frontend/src/components/SearchBox.vue b/web/frontend/src/components/SearchBox.vue index 59a7bc0e5..d480af0b7 100644 --- a/web/frontend/src/components/SearchBox.vue +++ b/web/frontend/src/components/SearchBox.vue @@ -155,6 +155,7 @@ export default defineComponent({ address: address, key: feature.properties.osm_id, position: position, + bbox: feature.bbox, gid: feature?.properties?.gid, }); } diff --git a/web/frontend/src/pages/PlacePage.vue b/web/frontend/src/pages/PlacePage.vue index 9fc442709..3b98ae40e 100644 --- a/web/frontend/src/pages/PlacePage.vue +++ b/web/frontend/src/pages/PlacePage.vue @@ -28,9 +28,19 @@ import SearchBox from 'src/components/SearchBox.vue'; async function loadPlacePage(router: Router, canonicalName: string) { const poi = await decanonicalizePoi(canonicalName); + if (poi === undefined) { + return poi; + } - if (poi?.position) { + if (poi.bbox) { + // prefer bounds when available so we don't "overzoom" on a large + // entity like an entire city. + getBaseMap()?.fitBounds(poi.bbox); + } else if (poi.position) { getBaseMap()?.flyTo([poi.position.long, poi.position.lat], 16); + } + + if (poi.position) { getBaseMap()?.pushMarker( 'active_marker', new Marker({ color: '#111111' }).setLngLat([ @@ -39,8 +49,9 @@ async function loadPlacePage(router: Router, canonicalName: string) { ]) ); getBaseMap()?.removeMarkersExcept(['active_marker']); - return poi; } + + return poi; } export default defineComponent({ diff --git a/web/frontend/src/utils/models.ts b/web/frontend/src/utils/models.ts index 273ecc349..4850bc188 100644 --- a/web/frontend/src/utils/models.ts +++ b/web/frontend/src/utils/models.ts @@ -72,6 +72,7 @@ export interface POI { name?: string | null; address?: string | null; position?: LongLat; + bbox?: [number, number, number, number]; gid?: string; } @@ -137,6 +138,7 @@ export async function decanonicalizePoi( address: address, key: feature.properties.osm_id, position: position, + bbox: feature.bbox, gid: feature?.properties?.gid, }; } From 64e348b553cee7b3c9803b88268f26cb7377dad3 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 17 Sep 2022 10:30:58 -0600 Subject: [PATCH 2/3] Avoid overzoom of small ways-POIs Some building POI's are stored as OSM ways, this means they have a bbox, but using that bbox for zoom results in feeling a bit too close - losing the valuable context of the surround block. An example of a too-close bbox zoom that this commit fixes: Victrola Coffee Roasters - "id": "way/206623301", --- web/frontend/src/components/BaseMap.vue | 14 ++++++++++---- web/frontend/src/pages/PlacePage.vue | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/web/frontend/src/components/BaseMap.vue b/web/frontend/src/components/BaseMap.vue index b4a45631e..3c2e3e55c 100644 --- a/web/frontend/src/components/BaseMap.vue +++ b/web/frontend/src/components/BaseMap.vue @@ -251,12 +251,18 @@ export default defineComponent({ this.$data.flyToLocation = { center: location, zoom: zoom }; } }, - fitBounds: async function (bounds: LngLatBoundsLike) { + fitBounds: async function ( + bounds: LngLatBoundsLike, + options: FitBoundsOptions = {} + ) { const permissionState = await geolocationPermissionState(); + const defaultOptions = { + padding: Math.min(window.innerWidth, window.innerHeight) / 8, + }; + options = { ...defaultOptions, ...(options || {}) }; + if (this.$data.hasGeolocated === true || permissionState !== 'granted') { - map?.fitBounds(bounds, { - padding: Math.min(window.innerWidth, window.innerHeight) / 8, - }); + map?.fitBounds(bounds, options); } else { this.$data.boundsToFit = bounds; } diff --git a/web/frontend/src/pages/PlacePage.vue b/web/frontend/src/pages/PlacePage.vue index 3b98ae40e..dbfe1aa83 100644 --- a/web/frontend/src/pages/PlacePage.vue +++ b/web/frontend/src/pages/PlacePage.vue @@ -35,7 +35,7 @@ async function loadPlacePage(router: Router, canonicalName: string) { if (poi.bbox) { // prefer bounds when available so we don't "overzoom" on a large // entity like an entire city. - getBaseMap()?.fitBounds(poi.bbox); + getBaseMap()?.fitBounds(poi.bbox, { maxZoom: 16 }); } else if (poi.position) { getBaseMap()?.flyTo([poi.position.long, poi.position.lat], 16); } From 5bb8bd57d0f982f65491a7c4218241b8862274d4 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 19 Sep 2022 10:55:49 -0700 Subject: [PATCH 3/3] prefer a named type for bbox --- web/frontend/src/utils/models.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/frontend/src/utils/models.ts b/web/frontend/src/utils/models.ts index 4850bc188..110aa5af3 100644 --- a/web/frontend/src/utils/models.ts +++ b/web/frontend/src/utils/models.ts @@ -1,5 +1,5 @@ import addressFormatter from '@fragaria/address-formatter'; -import {} from 'maplibre-gl'; +import { LngLatBoundsLike } from 'maplibre-gl'; import { i18n } from 'src/i18n/lang'; import { LongLat } from './geomath'; @@ -72,7 +72,7 @@ export interface POI { name?: string | null; address?: string | null; position?: LongLat; - bbox?: [number, number, number, number]; + bbox?: LngLatBoundsLike; gid?: string; }