Mapkit won't center?
Hey all, I'm evaluating using this project for a small demo.
I'm using this code, where marker and coords are identical objects.
<Map
token={process.env.REACT_APP_MAPKIT_KEY || ""}
initialRegion={{
centerLatitude: coords.lat,
centerLongitude: coords.lng,
latitudeDelta: 0.2,
longitudeDelta: 0.2
}}
cameraBoundary={{
centerLatitude: coords.lat,
centerLongitude: coords.lng,
latitudeDelta: 0.2,
longitudeDelta: 0.2
}}
>
{marker && <Marker
latitude={marker.lat}
longitude={marker.lng}
title={marker.location}
/>}
</Map>
The Map is part of a flexbox component that looks roughly like;
._____________________.
| MAP HERE | |
|----------| |
|__________|__________|
Whenever I update coordinates with cameraBoundary, the map always centers on the bottom left of the boundary area.
Something I noticed when inspecting the HTML;
<div class="mk-map-view mk-disable-all-gestures" style="position: relative;">
<canvas width="1122" height="494" class="syrup-canvas" aria-hidden="true" style="width: 561px; height: 247px; background-color: rgb(249, 245, 237);"></canvas>
<canvas class="rt-root" lang="en-US" dir="ltr" aria-hidden="true" width="1122" height="494" style="width: 561px; height: 247px;"></canvas>
<div class="mk-map-node-element" style="width: 561px; height: 247px;">
<div class="mk-annotation-container" lang="en-US"></div>
<div class="mk-controls-container" lang="en-US" style="inset: 0px;"></div>
</div>
</div>
You'll notice the canvas width and height values are double the style values. My window.devicePixelRatio setting is set to 2, and I think this may be related to the cause.
Any chance y'all can fix this? I'm happy to just use the default MapKit library but this seemed like a neat and simple solution.
Just to be clear; sometimes the marker isn't even inside of the visible map range when I update coords and marker. I have verified that they are identical objects / have the same values.
Hi @khorwood-openai,
Thank you for your interest in mapkit-react!
The strange behavior you are facing seems to come from MapKit JS itself. The cameraBoundary property available in mapkit-react maps directly to cameraBoundary in MapKit JS. It only controls the range the user is allowed to pan the camera in, not the actual position of the camera. When setting it after map initialization, it seems that MapKit JS will try to move the camera to the closest location where it would fit the new camera boundary, which is not what you want.
What I would suggest doing instead is to use MapKit JS’s imperative API (which is available when using mapkit-react through ref) to move the camera whenever you need:
import React, { useRef, useState } from 'react';
import { Map, Marker } from 'mapkit-react';
const token = "…";
export const MapWithMovingMarker = () => {
const locations = [
{ name: 'Jet d’eau', latitude: 46.20738751546706, longitude: 6.155891756231 },
{ name: 'Horloge fleurie', latitude: 46.20418989653241, longitude: 6.150997214058191 },
{ name: 'Bains des Pâquis', latitude: 46.21042332922134, longitude: 6.154311850592231 },
];
const [selectedLocationIndex, setSelectedLocationIndex] = useState(0);
const selectedLocation = locations[selectedLocationIndex];
const mapRef = useRef<mapkit.Map | null>(null);
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<div style={{ flex: 1 }}>
<Map
initialRegion={{
centerLatitude: selectedLocation.latitude,
centerLongitude: selectedLocation.longitude,
latitudeDelta: 0.005,
longitudeDelta: 0.005,
}}
token={token}
ref={mapRef}
>
<Marker
latitude={selectedLocation.latitude}
longitude={selectedLocation.longitude}
title={selectedLocation.name}
/>
</Map>
</div>
<div style={{ padding: '1rem' }}>
<select
value={selectedLocationIndex}
onChange={(e) => {
const newIndex = Number(e.target.value);
setSelectedLocationIndex(newIndex);
mapRef.current?.setCenterAnimated(new mapkit.Coordinate(
locations[newIndex].latitude,
locations[newIndex].longitude,
));
}}
>
{locations.map((location, index) => (
<option key={location.name} value={index}>{location.name}</option>
))}
</select>
</div>
</div>
);
};
https://github.com/user-attachments/assets/f5269673-c351-4ec8-bcae-a172d7cc3a9c
How can you center and zoom in?
@passatgt You can use setRegionAnimated or setCameraDistanceAnimated.
Thanks, thats what i figured. Its a bit difficoult to use setRegionAnimated, because you don't actually set zoom level, but the visible area diameter. And doing setCenterAnimated with setCameraDistanceAnimated doesn't seem to work if you run them both at the same time. Kinda weird we don't have a simple zoom levels like Google Maps from 0 to 22 or something like that.
Thanks, thats what i figured. Its a bit difficoult to use setRegionAnimated, because you don't actually set zoom level, but the visible area diameter. And doing setCenterAnimated with setCameraDistanceAnimated doesn't seem to work if you run them both at the same time. Kinda weird we don't have a simple zoom levels like Google Maps from 0 to 22 or something like that.
yeah... I am having a hard time adjusting to the map too. Also I don't know if it is just me but the document from Apple seems really hard to read and know what the hack I have to do with. I don't see any example or anything like that to have a clue. Like glyphImage. It says 'Object' but what object haha
Thanks, thats what i figured. Its a bit difficoult to use setRegionAnimated, because you don't actually set zoom level, but the visible area diameter. And doing setCenterAnimated with setCameraDistanceAnimated doesn't seem to work if you run them both at the same time. Kinda weird we don't have a simple zoom levels like Google Maps from 0 to 22 or something like that.
yeah... I am having a hard time adjusting to the map too. Also I don't know if it is just me but the document from Apple seems really hard to read and know what the hack I have to do with. I don't see any example or anything like that to have a clue. Like glyphImage. It says 'Object' but what object haha
This is my project, looks and kinda works nice: https://points.kvikk.hu But definitely a steep learning curve, but going to be a lot cheaper compared to Google Maps.
Hi @khorwood-openai,
Thank you for your interest in mapkit-react!
The strange behavior you are facing seems to come from MapKit JS itself. The
cameraBoundaryproperty available in mapkit-react maps directly tocameraBoundaryin MapKit JS. It only controls the range the user is allowed to pan the camera in, not the actual position of the camera. When setting it after map initialization, it seems that MapKit JS will try to move the camera to the closest location where it would fit the new camera boundary, which is not what you want.What I would suggest doing instead is to use MapKit JS’s imperative API (which is available when using mapkit-react through
ref) to move the camera whenever you need:import React, { useRef, useState } from 'react'; import { Map, Marker } from 'mapkit-react'; const token = "…"; export const MapWithMovingMarker = () => { const locations = [ { name: 'Jet d’eau', latitude: 46.20738751546706, longitude: 6.155891756231 }, { name: 'Horloge fleurie', latitude: 46.20418989653241, longitude: 6.150997214058191 }, { name: 'Bains des Pâquis', latitude: 46.21042332922134, longitude: 6.154311850592231 }, ]; const [selectedLocationIndex, setSelectedLocationIndex] = useState(0); const selectedLocation = locations[selectedLocationIndex]; const mapRef = useRef<mapkit.Map | null>(null); return ( <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}> <div style={{ flex: 1 }}> <Map initialRegion={{ centerLatitude: selectedLocation.latitude, centerLongitude: selectedLocation.longitude, latitudeDelta: 0.005, longitudeDelta: 0.005, }} token={token} ref={mapRef} > <Marker latitude={selectedLocation.latitude} longitude={selectedLocation.longitude} title={selectedLocation.name} /> </Map> </div> <div style={{ padding: '1rem' }}> <select value={selectedLocationIndex} onChange={(e) => { const newIndex = Number(e.target.value); setSelectedLocationIndex(newIndex); mapRef.current?.setCenterAnimated(new mapkit.Coordinate( locations[newIndex].latitude, locations[newIndex].longitude, )); }} > {locations.map((location, index) => ( <option key={location.name} value={index}>{location.name}</option> ))} </select> </div> </div> ); };Screenshot.2024-09-08.at.12.03.36.mov
Heya! In order to do this, do I have to add
to html? BTW, thanks you so much for the great package :)
Hey @parttiez, thank you for your interest in mapkit-react!
You don’t need to add <script> tags when using mapkit-react, it will automatically load the necessary script from Apple’s CDN. If you would like to change the way the script is loaded (for instance because you only want to load only some parts of MapKit JS instead of the entire bundle to improve your app’s performance), you can use the load parameter of <Map />.
Don’t forget to include a correct value for token (you can learn how to generate one from Apple’s documentation).