Si vous souhaitez simplement figer la vue de la carte au niveau de la superposition, vous pouvez définir la région de la vue de la carte aux limites de la superposition et définir l'option scrollEnabled
y zoomEnabled
a NO
.
Mais cela ne permet pas à l'utilisateur de faire défiler ou de zoomer à l'intérieur des limites du recouvrement.
Il n'existe pas de moyens intégrés pour restreindre l'affichage de la carte aux limites de la superposition, vous devez donc le faire manuellement. Tout d'abord, assurez-vous que votre MKOverlay
met en œuvre l'objet boundingMapRect
propriété. Celle-ci peut alors être utilisée dans le regionDidChangeAnimated
pour ajuster manuellement la vue si nécessaire.
Voici un exemple de la façon dont cela pourrait être fait.
Le code ci-dessous doit se trouver dans la classe qui possède le code MKMapView
.
Assurez-vous que la vue de la carte est initialement réglée sur une région où la superposition est visible.
//add two ivars to the .h...
MKMapRect lastGoodMapRect;
BOOL manuallyChangingMapRect;
//in the .m...
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect)
return;
lastGoodMapRect = mapView.visibleMapRect;
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
if (manuallyChangingMapRect) //prevents possible infinite recursion when we call setVisibleMapRect below
return;
// "theOverlay" below is a reference to your MKOverlay object.
// It could be an ivar or obtained from mapView.overlays array.
BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);
if (mapContainsOverlay)
{
// The overlay is entirely inside the map view but adjust if user is zoomed out too much...
double widthRatio = theOverlay.boundingMapRect.size.width / mapView.visibleMapRect.size.width;
double heightRatio = theOverlay.boundingMapRect.size.height / mapView.visibleMapRect.size.height;
if ((widthRatio < 0.6) || (heightRatio < 0.6)) //adjust ratios as needed
{
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
manuallyChangingMapRect = NO;
}
}
else
if (![theOverlay intersectsMapRect:mapView.visibleMapRect])
{
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
}
}
J'ai essayé avec la fonction intégrée MKCircle
et semble bien fonctionner.
EDIT :
Il fonctionne bien 95 % du temps, mais j'ai confirmé par des tests qu'il pouvait osciller entre deux emplacements, puis entrer dans une boucle infinie. Je l'ai donc modifié un peu, et je pense que cela devrait résoudre le problème :
// You can safely delete this method:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
// prevents possible infinite recursion when we call setVisibleMapRect below
if (manuallyChangingMapRect) {
return;
}
// "theOverlay" below is a reference to your MKOverlay object.
// It could be an ivar or obtained from mapView.overlays array.
BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);
if (mapContainsOverlay) {
// The overlay is entirely inside the map view but adjust if user is zoomed out too much...
double widthRatio = theOverlay.boundingMapRect.size.width / mapView.visibleMapRect.size.width;
double heightRatio = theOverlay.boundingMapRect.size.height / mapView.visibleMapRect.size.height;
// adjust ratios as needed
if ((widthRatio < 0.6) || (heightRatio < 0.6)) {
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
manuallyChangingMapRect = NO;
}
} else if (![theOverlay intersectsMapRect:mapView.visibleMapRect]) {
// Overlay is no longer visible in the map view.
// Reset to last "good" map rect...
manuallyChangingMapRect = YES;
[mapView setVisibleMapRect:lastGoodMapRect animated:YES];
manuallyChangingMapRect = NO;
} else {
lastGoodMapRect = mapView.visibleMapRect;
}
}
Et juste au cas où quelqu'un chercherait à obtenir rapidement une MKOverlay
Voici une solution :
- (void)viewDidLoad {
[super viewDidLoad];
MKCircle* circleOverlay = [MKCircle circleWithMapRect:istanbulRect];
[_mapView addOverlay:circleOverlay];
theOverlay = circleOverlay;
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
MKCircleView* circleOverlay = [[MKCircleView alloc] initWithCircle:overlay];
[circleOverlay setStrokeColor:[UIColor mainColor]];
[circleOverlay setLineWidth:4.f];
return circleOverlay;
}