2011-08-22 21 views
4

你知道如何創建一個動畫像MKMapView中的藍色大理石滴用戶位置?iphone - 像用戶位置創建動畫藍色大理石滴

+1

你是說你願意做一個類似的動畫,或者你想有標準位置指示器在地圖視圖中顯示出來? –

+0

我喜歡製作類似的動畫,謝謝。 –

+0

你的答案後發現 [此處輸入鏈接的描述] [1] [1]:http://stackoverflow.com/questions/1437568/howto-initialise-mkmapview-with-a-given用戶位置 –

回答

11

雖然我不知道對蘋果如何實現這種效果的細節,這種感覺對我來說,使用CoreAnimation和自定義動畫性能的絕佳機會。 This post爲這個主題提供了一些不錯的背景。我想通過你指的是按以下順序的「藍色大理石降」動畫:

  1. 大淡藍色圓圈放大到幀的兩個比較大的半徑之間
  2. 大淡藍色的圓圈作爲振盪位置 計算
  3. 大淡藍色圓圈放大到小的深藍色圓圈用戶的位置

儘管這可能會稍微簡化這個過程中,我認爲這是一個開始,更復雜的/詳細的功能下的好地方可以相對容易地添加(即小黑眼圈脈衝作爲大圈收斂就可以了)

我們首先需要的是一個自定義CALayer的子類,與我們的外部大蔥白圈半徑的自定義屬性:

#import <QuartzCore/QuartzCore.h> 

@interface CustomLayer : CALayer 
@property (nonatomic, assign) CGFloat circleRadius; 
@end 

和實現:

#import "CustomLayer.h" 

@implementation CustomLayer 
@dynamic circleRadius; // Linked post tells us to let CA implement our accessors for us. 
         // Whether this is necessary or not is unclear to me and one 
         // commenter on the linked post claims success only when using 
         // @synthesize for the animatable property. 

+ (BOOL)needsDisplayForKey:(NSString*)key { 
    // Let our layer know it has to redraw when circleRadius is changed 
    if ([key isEqualToString:@"circleRadius"]) { 
     return YES; 
    } else { 
     return [super needsDisplayForKey:key]; 
    } 
} 

- (void)drawInContext:(CGContextRef)ctx { 

    // This call is probably unnecessary as super's implementation does nothing 
    [super drawInContext:ctx]; 

    CGRect rect = CGContextGetClipBoundingBox(ctx); 

    // Fill the circle with a light blue 
    CGContextSetRGBFillColor(ctx, 0, 0, 255, 0.1); 
    // Stoke a dark blue border 
    CGContextSetRGBStrokeColor(ctx, 0, 0, 255, 0.5); 

    // Construct a CGMutablePath to draw the light blue circle 
    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathAddArc(path, NULL, rect.size.width/2, 
          rect.size.height/2, 
          self.circleRadius, 0, 2 * M_PI, NO); 
    // Fill the circle 
    CGContextAddPath(ctx, path); 
    CGContextFillPath(ctx); 

    // Stroke the circle's border 
    CGContextAddPath(ctx, path); 
    CGContextStrokePath(ctx); 

    // Release the path 
    CGPathRelease(path); 

    // Set a dark blue color for the small inner circle 
    CGContextSetRGBFillColor(ctx, 0, 0, 255, 1.0f); 

    // Draw the center dot 
    CGContextBeginPath (ctx); 
    CGContextAddArc(ctx, rect.size.width/2, 
         rect.size.height/2, 
         5, 0, 2 * M_PI, NO); 
    CGContextFillPath(ctx); 
    CGContextStrokePath(ctx); 

} 

@end 

有了這個基礎設施的地方,我們現在可以動畫輕鬆b/C CoreAnimation外圓半徑會照顧值插補以及重繪電話。我們所要做的就是給圖層添加一個動畫。作爲概念的一個簡單證明,我選擇了一個簡單CAKeyframeAnimation要經過3個階段的動畫:

// In some controller class... 
- (void)addLayerAndAnimate { 

    CustomLayer *customLayer = [[CustomLayer alloc] init]; 

    // Make layer big enough for the initial radius 
    // EDIT: You may want to shrink the layer when it reacehes it's final size 
    [customLayer setFrame:CGRectMake(0, 0, 205, 205)]; 
    [self.view.layer addSublayer:customLayer]; 


    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"circleRadius"]; 

    // Zoom in, oscillate a couple times, zoom in further 
    animation.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:100], 
               [NSNumber numberWithFloat:45], 
               [NSNumber numberWithFloat:50], 
               [NSNumber numberWithFloat:45], 
               [NSNumber numberWithFloat:50], 
               [NSNumber numberWithFloat:45], 
               [NSNumber numberWithFloat:20], 
                nil]; 
    // We want the radii to be 20 in the end 
    customLayer.circleRadius = 20; 

    // Rather arbitrary values. I thought the cubic pacing w/ a 2.5 second pacing 
    // looked decent enough but you'd probably want to play with them to get a more 
    // accurate imitation of the Maps app. You could also define a keyTimes array for 
    // a more discrete control of the times per step. 
    animation.duration = 2.5; 
    animation.calculationMode = kCAAnimationCubicPaced; 

    [customLayer addAnimation:animation forKey:nil]; 

} 

以上是概念的,而「哈克」的證明,因爲我不知道具體的方法在其中打算用這個效果。例如,如果你想振盪圓圈直到數據準備就緒,上述情況就不會有多大意義,因爲它總是會振盪兩次。

有些收盤筆記:

  • 同樣,我不知道你的意圖,這種效果的。例如,對於 示例,如果將它添加到MKMapView,以上可能需要 進行一些調整才能與MapKit集成。
  • 的鏈接後顯示上述方法需要CoreAnimation中的iOS 3.0+和OS X 10.6+鏈接後
  • 漢化的版本(像我一樣經常),大部分功勞和感謝奧萊Begemann誰寫it和在CoreAnimation中解釋自定義屬性做了很棒的工作。

編輯:此外,對於性能方面的原因,你可能會想,以確保該層是唯一的,因爲它需要儘可能大。也就是說,在從較大尺寸完成動畫後,您可能需要縮小尺寸,以便只使用/繪製儘可能多的空間。這樣做的一個好方法就是找到一個動畫bounds(而不是circleRadius)的動畫並基於尺寸插值執行此動畫,但是我在實現該動畫時遇到了一些問題(也許有人可以在該主題上添加一些洞察) 。

希望這有助於 山姆

+0

線條和中間的藍色圓圈像素化,鋸齒狀..我可以做的任何事情來解決這個問題,使光滑? – Zsolt

+0

想通了.. customLayer.contentsScale = [UIScreen mainScreen] .scale; – Zsolt

-2

添加到您的地圖對象:

myMap.showsUserLocation = TRUE;