dimfeld / svelte-maplibre

Svelte bindings for the MapLibre mapping library
https://svelte-maplibre.vercel.app
MIT License
319 stars 40 forks source link

Bounds doesn't work properly #115

Closed SiddHyper closed 9 months ago

SiddHyper commented 9 months ago

Hi I am using the below native Maplibre code to extend the bounds

/**
 * Combine bounds of array of point or bounds elements
 */
export function reduceBounds(elements: Maybe<PointOrBounds>[]) {
  const bounds = new LngLatBounds();
  elements.forEach((element) => {
    if (element) {
      bounds.extend(element);
    }
  });
  return bounds;
}

and I have a AutoBounds.svelte like below

<script lang="ts">
  import type { Map } from 'svelte-maplibre';
  import { reduceBounds } from '../../lib/utils';
  import type { Maybe, PointOrBounds } from '../../types/common.type';
  import type { LngLatLike } from 'maplibre-gl';

  export let elements: Maybe<PointOrBounds>[] = [];
  export let map: Map | null;

  $: {
    if (elements.length > 0) {
      const bounds = reduceBounds(elements);
      if (map && !bounds.isEmpty() && elements.length > 0) {
        console.debug('fitting bounds', { elements }, bounds);
        map.fitBounds(bounds, {
          padding: 80,
          duration: 2000,
          maxZoom: 17,
        });
      }
    }
  }
</script>

Map is coming from let:map fo Maplibre Component and elements are array of lng

export type PointOrBounds = LngLatLike | LngLatBoundsLike;

I get and error like below

svelte-maplibre.js?v=5521f210:10531 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'lng')
    at L2.getWest (svelte-maplibre.js?v=5521f210:10531:29)
    at L2.getNorthWest (svelte-maplibre.js?v=5521f210:10525:33)
    at Ba.Map.cameraForBounds (svelte-maplibre.js?v=5521f210:16331:52)
    at Ba.Map.fitBounds (svelte-maplibre.js?v=5521f210:16347:43)
    at $$self.$$.update (AutoBounds.svelte:14:13)
    at update (chunk-3G3EV4QO.js?v=5521f210:1323:8)
    at flush (chunk-3G3EV4QO.js?v=5521f210:1293:9)
    at update2 (chunk-3G3EV4QO.js?v=5521f210:1696:7)
    at chunk-3G3EV4QO.js?v=5521f210:1704:9
SiddHyper commented 9 months ago

the hack I have to do is directly use lnglatArray but that also have a bug it seems it works for more than one elements if there is one elements it thorws error

 if (elements.length === 1) {
        //@ts-ignore
        map.fitBounds([...elements, ...elements], {
          padding: 80,
          duration: 2000,
          maxZoom: 17,
        });
      } else {
        //@ts-ignore
        map.fitBounds(elements, {
          padding: 80,
          duration: 2000,
          maxZoom: 17,
        });
      }
dimfeld commented 9 months ago

If you're calling map.fitBounds that shouldn't have anything to do with the code in this library since you're talking directly to the map instance (which is fine, but I can't do anything to alter that experience).

Are you sure that the elements you're passing in are actually a valid argument for fitBounds?

Likewise, in the case of elements.length == 1 I would expect an error because a single point is not a valid bounds.

(See https://maplibre.org/maplibre-gl-js/docs/API/classes/maplibregl.Map/#fitbounds and https://maplibre.org/maplibre-gl-js/docs/API/types/maplibregl.LngLatBoundsLike/)

SiddHyper commented 9 months ago

@dimfeld I have used the same code with the library it worked perfectly fine and bounds do support only one lnglat if you use new LngLatBounds Class

SiddHyper commented 9 months ago

And I m not sure why const bounds = new LngLatBounds(); this doesn't work

SiddHyper commented 9 months ago

@dimfeld This seems to work the issue was I had installed the older version of maplibre 3.3.1 and I noticed you were using 3.5.0 when I change to this it works fine so closing this Thanks for your reply 😄