ビューForAnnotationで自分の画像を設定するカスタムMKAnnotationViewがあります。 MKPinAnnotationViewでできるように、ドロップをアニメーション化するにはどうすればよいですか?
私のコードは
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *AnnotationViewID = @"annotationViewID";
MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
if (annotationView == nil)
{
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID] autorelease];
}
annotationView.image = [UIImage imageNamed:@"blah.png"];
annotationView.annotation = annotation;
return annotationView;
}
didAddAnnotationViews
デリゲートメソッドを実装し、アニメーションを自分で実行します。
- (void)mapView:(MKMapView *)mapView
didAddAnnotationViews:(NSArray *)annotationViews
{
for (MKAnnotationView *annView in annotationViews)
{
CGRect endFrame = annView.frame;
annView.frame = CGRectOffset(endFrame, 0, -500);
[UIView animateWithDuration:0.5
animations:^{ annView.frame = endFrame; }];
}
}
Anna Kareninaによる上記のコードの問題の1つは、ユーザーが現在見ている場所の下に注釈を追加すると、処理されないことです。これらの注釈は、ユーザーの表示可能なマップrectに移動されるため、ドロップする前に空中に浮きます。
もう1つは、ユーザーの場所の青い点も削除することです。以下のこのコードを使用すると、ユーザーの場所と大量の地図注釈の両方を画面外で処理できます。ニースバウンスも追加しました;)
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV;
for (aV in views) {
// Don't pin drop if annotation is user location
if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
continue;
}
// Check if current annotation is inside visible map rect, else go to next one
MKMapPoint point = MKMapPointForCoordinate(aV.annotation.coordinate);
if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
continue;
}
CGRect endFrame = aV.frame;
// Move annotation out of view
aV.frame = CGRectMake(aV.frame.Origin.x, aV.frame.Origin.y - self.view.frame.size.height, aV.frame.size.width, aV.frame.size.height);
// Animate drop
[UIView animateWithDuration:0.5 delay:0.04*[views indexOfObject:aV] options: UIViewAnimationOptionCurveLinear animations:^{
aV.frame = endFrame;
// Animate squash
}completion:^(BOOL finished){
if (finished) {
[UIView animateWithDuration:0.05 animations:^{
aV.transform = CGAffineTransformMakeScale(1.0, 0.8);
}completion:^(BOOL finished){
if (finished) {
[UIView animateWithDuration:0.1 animations:^{
aV.transform = CGAffineTransformIdentity;
}];
}
}];
}
}];
}
}
@MrAlekの答えSwift
optional func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
print(#function)
var i = -1;
for view in views {
i += 1;
if view.annotation is MKUserLocation {
continue;
}
// Check if current annotation is inside visible map rect, else go to next one
let point:MKMapPoint = MKMapPointForCoordinate(view.annotation!.coordinate);
if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
continue;
}
let endFrame:CGRect = view.frame;
// Move annotation out of view
view.frame = CGRect(Origin: CGPoint(x: view.frame.Origin.x,y :view.frame.Origin.y-self.view.frame.size.height), size: CGSize(width: view.frame.size.width, height: view.frame.size.height))
// Animate drop
let delay = 0.03 * Double(i)
UIView.animate(withDuration: 0.5, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations:{() in
view.frame = endFrame
// Animate squash
}, completion:{(Bool) in
UIView.animate(withDuration: 0.05, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations:{() in
view.transform = CGAffineTransform(scaleX: 1.0, y: 0.6)
}, completion: {(Bool) in
UIView.animate(withDuration: 0.3, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations:{() in
view.transform = CGAffineTransform.identity
}, completion: nil)
})
})
}
}
@MrAlekの答えSwift 2:
func mapView(mapView: MKMapView, didAddAnnotationViews views: [MKAnnotationView]) {
print(__FUNCTION__)
var i = -1;
for view in views {
i++;
if view.annotation is MKUserLocation {
continue;
}
// Check if current annotation is inside visible map rect, else go to next one
let point:MKMapPoint = MKMapPointForCoordinate(view.annotation!.coordinate);
if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
continue;
}
let endFrame:CGRect = view.frame;
// Move annotation out of view
view.frame = CGRectMake(view.frame.Origin.x, view.frame.Origin.y - self.view.frame.size.height, view.frame.size.width, view.frame.size.height);
// Animate drop
let delay = 0.03 * Double(i)
UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations:{() in
view.frame = endFrame
// Animate squash
}, completion:{(Bool) in
UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
view.transform = CGAffineTransformMakeScale(1.0, 0.6)
}, completion: {(Bool) in
UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
view.transform = CGAffineTransformIdentity
}, completion: nil)
})
})
}
}
Swiftでの@mrAlekの回答:
func mapView(mapView: MKMapView!, didAddAnnotationViews views: [AnyObject]!) {
println("didAddAnnotationViews()")
var i = -1;
for view in views {
i++;
let mkView = view as! MKAnnotationView
if view.annotation is MKUserLocation {
continue;
}
// Check if current annotation is inside visible map rect, else go to next one
let point:MKMapPoint = MKMapPointForCoordinate(mkView.annotation.coordinate);
if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
continue;
}
let endFrame:CGRect = mkView.frame;
// Move annotation out of view
mkView.frame = CGRectMake(mkView.frame.Origin.x, mkView.frame.Origin.y - self.view.frame.size.height, mkView.frame.size.width, mkView.frame.size.height);
// Animate drop
let delay = 0.03 * Double(i)
UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations:{() in
mkView.frame = endFrame
// Animate squash
}, completion:{(Bool) in
UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
mkView.transform = CGAffineTransformMakeScale(1.0, 0.6)
}, completion: {(Bool) in
UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
mkView.transform = CGAffineTransformIdentity
}, completion: nil)
})
})
}
}
Swift 4.2用に更新
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
var i = -1;
for view in views {
i += 1;
if view.annotation is MKUserLocation {
continue;
}
let point:MKMapPoint = MKMapPoint(view.annotation!.coordinate);
if (!self.mapView.visibleMapRect.contains(point)) {
continue;
}
let endFrame:CGRect = view.frame;
view.frame = CGRect(Origin: CGPoint(x: view.frame.Origin.x,y :view.frame.Origin.y-self.view.frame.size.height), size: CGSize(width: view.frame.size.width, height: view.frame.size.height))
let delay = 0.03 * Double(i)
UIView.animate(withDuration: 0.5, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations:{() in
view.frame = endFrame
}, completion:{(Bool) in
UIView.animate(withDuration: 0.05, delay: 0.0, options: UIView.AnimationOptions.curveEaseInOut, animations:{() in
view.transform = CGAffineTransform(scaleX: 1.0, y: 0.6)
}, completion: {(Bool) in
UIView.animate(withDuration: 0.3, delay: 0.0, options: UIView.AnimationOptions.curveEaseInOut, animations:{() in
view.transform = CGAffineTransform.identity
}, completion: nil)
})
})
}
}