Comments (7)
I found a way to work around this, by not passing these props and using the on:load
callback instead. Specifically, I did this:
<MapLibre
style={{...}}
on:load={(event) => {
const map = event.detail;
feature.subscribe(($feature) => {
if ($feature) {
const bounds = $feature.properties.bounds;
if (bounds) {
const camera = map.cameraForBounds(bounds);
map.jumpTo(camera);
} else {
map.jumpTo({
center: $feature.geometry.coordinates
});
}
}
});
}}
/>
Since there is a workaround to allow the developer to take full control of how to handle these props changing, it's perfectly reasonable to expose a simpler API that is limited in its flexibility. Maybe this would be enough:
<MapLibre
style={{...}}
center={$center}
bounds={$bounds}
animationOptions={{
center: {
duration: 500,
},
bounds: {
animate: false
}
}}
/>
Where this animationOptions
object has keys of center
, bounds
, and zoom
(and possibly others?), and the values are AnimationOptions
objects. Naturally, these values are passed to the panTo()
, zoomTo()
, and fitBounds()
functions.
For developers who need more control than this, it's probably enough to clearly document how they can use the on:load
callback to do it manually, the way I did.
from svelte-maplibre.
Yeah I agree this is a nice feature to have. Here are two possibilities; I'm not sure yet which one I prefer (or something else I haven't thought of!).
Option to Disable Reactivity
interface Reactive {
center?: boolean;
zoom?: boolean;
bounds?: boolean;
}
export let reactive: boolean | Reactive = true;
$: isReactive = typeof reactive === 'boolean'
? { center: reactive, zoom: reactive, bounds: reactive }
: reactive.
$: if (center && isReactive.center && !compare(center, $mapInstance?.getCenter())) $mapInstance?.panTo(center);
$: if (zoom && isReactive.zoom && !compare(zoom, $mapInstance?.getZoom())) $mapInstance?.zoomTo(zoom);
$: if (bounds && isReactive.bounds && !compare(bounds, $mapInstance?.getBounds())) $mapInstance?.fitBounds(bounds);
Pros and Cons:
- pro: Flexible since you're basically taking full responsibility for handling these props
- con: you're basically taking full responsibility for handling these props :)
Custom Callback
Another possibility would be the option to supply a custom callback to apply these changes, which would be called when any of them change. Something like this:
export let applyBounds: (({ map, zoom, center, bounds }) => unknown) | undefined = undefined;
$: if (applyBounds && (
(center && !compare(center, $mapInstance?.getCenter()) ||
(zoom && !compare(zoom, $mapInstance?.getZoom()) ||
(bounds && !compare(bounds, $mapInstance?.getBounds()) ) {
applyBounds({ map: $mapInstance, center, zoom, bounds });
}
$: if (!applyBounds && center && !compare(center, $mapInstance?.getCenter())) $mapInstance?.panTo(center);
$: if (!applyBounds && zoom && !compare(zoom, $mapInstance?.getZoom())) $mapInstance?.zoomTo(zoom);
$: if (!applyBounds && bounds && !compare(bounds, $mapInstance?.getBounds())) $mapInstance?.fitBounds(bounds);
Pros and Cons of this approach
- pro: it doesn't require you to implement your own reactive logic outside the map to handle these changes
- pro: easy to handle things like simultaneous changes to center and zoom resulting in a single API call
- con: perhaps harder to see what changed in the callback (though we could just pass the old values or a set of
changed
flags to the callback to help with this) - con: the applyBounds callback could do something that doesn't result in those
compare
calls returning true, which might be valid for the use case but could result in weird behavior or the callback being called infinitely.
Given that last con, I think the first option to just allow disabling reactivity could work the best.
from svelte-maplibre.
Planning to implement this next week
from svelte-maplibre.
Glad you found something that worked, and thanks for the suggestion on the API! That does feel like a good middle ground while leaving the option to do something more advanced like what you ended up doing.
from svelte-maplibre.
This automatic behavior also seems to be responsible for unwanted movement when viewing 3D terrain:
Adding the suggested option to disable reactivity (and then disabling it) stops this from happening.
from svelte-maplibre.
Maybe I'm wrong but it seems like the current behaviour
$: if (center && !compare(center, $mapInstance?.getCenter())) $mapInstance?.panTo(center);
$: if (zoom && !compare(zoom, $mapInstance?.getZoom())) $mapInstance?.zoomTo(zoom);
does not allow changing both zoom and map center together. Maplibre will zoom properly, fire a moveend
event, and forget about finishing panning to the center.
e.g. clicking the button below will zoom but panning won't be performed properly
//...
let c = [-9.142685, 38.736946];
let z = 2;
</script>
<button on:click={() => {
c = [-3.13, 17.73];
z = 6;
}}>Jump somewhere else</button>
<MapLibre
style="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
center={c}
zoom={z}
//...
from svelte-maplibre.
@timadevelop yeah makes sense, it would probably be better to combine both of those into a call into map.easeTo
instead.
from svelte-maplibre.
Related Issues (20)
- Removing Markers and LineLayer HOT 1
- Upport for Svelte 5? HOT 1
- add marker on click HOT 4
- Add 3D Terrain components
- flyTo doesn't properly center to the LngLat value of the marker HOT 4
- Certain reactive properties in layer paint property do not update the map when changed
- Combine zoom and center handling into a single call to map.easeTo
- Programmatically trigger GeolocateControl HOT 3
- Warning when using history.replaceState with SvelteKit HOT 4
- allow re-use of map instance on re-mount HOT 2
- Animate a line on the map HOT 1
- Generated type for `Popup` slot `features` attribute is `null` HOT 1
- Upgrade deck.gl dependency to 9.0
- Change some uses of null to undefined
- DeckGlLayer fails to load after changing basemap HOT 2
- Marker popup remains when opening another marker HOT 2
- Zoom range for vector layer. HOT 2
- Test with Svelte 5 HOT 1
- Build with own maplibre-gl HOT 2
- FillLayer does not react on hover HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from svelte-maplibre.