IOS CALayer實現圓點繞圓周運動--CAKeyframeAnimation的使用

效果圖如下:



android的做法是,擴展一個View然後畫一個圓點,再通過一個動畫來不改變這個圓點的座標即可。

IOS的做法一:展示這個小圓點方法同android,但是圓點的座標變換通過定時器,代碼如下:


-(void) playAnim{

    NSDate *scheduledTime = [NSDate dateWithTimeIntervalSinceNow:0];
    NSTimer *timer = [[NSTimer alloc] initWithFireDate:scheduledTime
                                              interval:0.00000001
                                                target:self
                                              selector:@selector(task)
                                              userInfo:nil
                                               repeats:YES];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
    
   

}

-(void)task {
    self.dAngle += 1;
    [self setNeedsDisplay];
    
}

-(void) stopAnim{

    
}

-(void) drawInContext:(CGContextRef)ctx{
    
    
    //畫圓
    CGContextSetRGBStrokeColor(ctx,0.52f, 0.76f, 0.07f, 1.0f);
    
    CGContextSetLineWidth(ctx, 2.0);
    
    //    CGContextAddArc(ctx, self.frame.size.width / 2 - 10, self.frame.size.height / 2, 25, 0, PI, 0);
    //
    //    CGContextAddArc(ctx, self.frame.size.width / 2 + 10, self.frame.size.height / 2, 25, 0, PI, 0);
    
    
    /*
     CGContextRef c:上下文
     CGFloat x :x,y圓弧所在圓的中心點座標
     CGFloat y :x,y圓弧所在圓的中心點座標
     CGFloat radius :所在圓的半徑
     CGFloat startAngle : 圓弧的開始的角度  單位是弧度  0對應的是最右側的點;
     CGFloat endAngle  : 圓弧的結束角度
     int clockwise : 順時針(0) 或者 逆時針(1)
     */
    CGContextAddArc(ctx, self.frame.size.width / 2, self.frame.size.height / 2, 25, 0,  2 * PI, 0);
    
    CGContextDrawPath(ctx, kCGPathStroke);
    
    
    //畫一個圓點,,將上面的定時器開啓可以達到圓點繞圓周運動
    CGContextSetRGBStrokeColor(ctx,0.12f, 0.26f, 0.07f, 1.0f);
    CGContextAddArc(ctx,
                    self.frame.size.width / 2 + cos(self.dAngle * PI / 180) * 25,
                    self.frame.size.height / 2 + sin(self.dAngle * PI / 180) * 25,
                    5,
                    0,
                    2 * PI,
                    0);
    CGContextDrawPath(ctx, kCGPathFillStroke);
    
}


@end

這種方法的缺點是是,小圓點的座標改變是線性變化,如果想達到淡入淡出的效果,需要自己支寫動畫插值器,難度有點大, 不推薦使用此方法。


針對方法一中的缺點,方法二有能有效解決這個問題。

方法二: 使用

CAKeyframeAnimation+UIBezierPath


其中UIBezierPath作爲小圓點的運動軌跡,CAKeyframeAnimation則用來改變小圓點的座標,在IOS中提供了幾種動畫運行的效果,很容易實現淡入淡出的效果。

其中,小圓點的運動軌跡應該與外面那個圓環一致,爲了方便操作,將小圓點所在的圖層作爲圓環的子圖層就可以不用進行座標轉換,如果2個圖片層爲兄弟關係就需要進行座標轉換,這裏大家稍微想想就很容易明白,爲什麼需要座標轉換。


外面圓環的代碼,:只要繪圖方法即可,

-(void) drawInContext:(CGContextRef)ctx{
    
    
    //畫圓
    CGContextSetRGBStrokeColor(ctx,0.52f, 0.76f, 0.07f, 1.0f);
    
    CGContextSetLineWidth(ctx, 2.0);
    
    //    CGContextAddArc(ctx, self.frame.size.width / 2 - 10, self.frame.size.height / 2, 25, 0, PI, 0);
    //
    //    CGContextAddArc(ctx, self.frame.size.width / 2 + 10, self.frame.size.height / 2, 25, 0, PI, 0);
    
    
    /*
     CGContextRef c:上下文
     CGFloat x :x,y圓弧所在圓的中心點座標
     CGFloat y :x,y圓弧所在圓的中心點座標
     CGFloat radius :所在圓的半徑
     CGFloat startAngle : 圓弧的開始的角度  單位是弧度  0對應的是最右側的點;
     CGFloat endAngle  : 圓弧的結束角度
     int clockwise : 順時針(0) 或者 逆時針(1)
     */
    CGContextAddArc(ctx, self.frame.size.width / 2, self.frame.size.height / 2, 25, 0,  2 * PI, 0);
    
    CGContextDrawPath(ctx, kCGPathStroke);
    
    
    //畫一個圓點,,將上面的定時器開啓可以達到圓點繞圓周運動
//    CGContextSetRGBStrokeColor(ctx,0.12f, 0.26f, 0.07f, 1.0f);
//    CGContextAddArc(ctx,
//                    self.frame.size.width / 2 + cos(self.dAngle * PI / 180) * 25,
//                    self.frame.size.height / 2 + sin(self.dAngle * PI / 180) * 25,
//                    5,
//                    0,
//                    2 * PI,
//                    0);
//    CGContextDrawPath(ctx, kCGPathFillStroke);
    
}



在vc中的測試代碼如下:

#import "PointMoveByCircleVC.h"
#import "PointMoveByCircleLayer.h"

@interface PointMoveByCircleVC ()

@property(nonatomic,strong) PointMoveByCircleLayer* layer;

@end

@implementation PointMoveByCircleVC

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initView];
}
-(void) initView{

    self.view.backgroundColor  = [UIColor whiteColor];
    
    self.layer = [PointMoveByCircleLayer layer];
    self.layer.dAngle = 0;
    self.layer.frame = CGRectMake(100, 100, 100, 100);
    
    [self.layer setNeedsDisplay];    //寫這個方法纔會自動觸發 drawInContext:的方法
    self.layer.backgroundColor = [UIColor brownColor].CGColor;
    
    [self.view.layer addSublayer:self.layer];
    
    
    UIButton* btnAnim = [[UIButton alloc] initWithFrame:CGRectMake(180, 240, 180, 30)];
    btnAnim.backgroundColor = [UIColor grayColor];
    btnAnim.tag = 13;
    [btnAnim setTitle:@"播放動畫" forState:UIControlStateNormal];
    [btnAnim addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btnAnim];
}

-(void) onClick:(UIButton*) button{

    switch (button.tag) {
            case 13:{
                
                //[self.layer playAnim];
                
                
                UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
                [bezierPath moveToPoint:CGPointMake(0, 150)];
                [bezierPath addCurveToPoint:CGPointMake(300, 150) controlPoint1:CGPointMake(75, 0) controlPoint2:CGPointMake(225, 300)];
                
                //初始化圓點層
                UIBezierPath* path = [[UIBezierPath alloc] init];
                [path addArcWithCenter:CGPointMake(self.layer.frame.size.width / 2, self.layer.frame.size.width / 2)
                                radius:25
                            startAngle:0
                              endAngle:2 * 3.1415926
                             clockwise:1];
                
                
                CALayer *colorLayer = [CALayer layer];
                colorLayer.frame = CGRectMake(0, 0, 5, 5);
                colorLayer.cornerRadius = 2.5;
                colorLayer.position = CGPointMake(self.layer.frame.size.width / 2 + cos(90 * 3.1415926 / 180) * 25,
                                                  self.layer.frame.size.width / 2 + sin(90 * 3.1415926 / 180) * 25);
                
                colorLayer.backgroundColor = [UIColor redColor].CGColor;
                [self.layer addSublayer:colorLayer];
                
                //創建一個幀動畫需要 的圓周 路徑,這個路徑 與外圓圈一一致
                CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
                animation1.keyPath = @"position";
                animation1.path = path.CGPath;
                animation1.duration = 1.0;
                animation1.repeatCount = MAXFLOAT;
                animation1.timingFunction =  [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
                
                
                [colorLayer addAnimation:animation1 forKey:nil];

                
        }
            break;
            
        default:
            break;
    }

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    
}



@end







發佈了151 篇原創文章 · 獲贊 10 · 訪問量 49萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章