CALayer position 和 anchorPoint 的問題

概要:

CALayerposition白話來講:position就是layer 自身的anchorPoint相對于父superLayer的坐標位置嘹朗。
常規(guī)說來师妙,在iOS上,一個圖層的position位于父圖層的左上角
具體概念參考:這將是你最后一次糾結(jié)position與anchorPoint

關(guān)于畫曲線的角度參考圖:


正文:

需求是一個掃描匹配的動畫:

hhhh.gif

如上展示的是最終的效果屹培。這里主要用的是一個自定義view PulsingView默穴,重寫 (void)drawRect:(CGRect)rect方法怔檩,在這個方法內(nèi)部去畫相應(yīng)的元素,主要包含:

  • 1.外部擴散的脈沖layer蓄诽。
  • 2.雷達掃面的內(nèi)圈layer薛训。
  • 3.雷達掃描的扇形layer。

首先是外部的脈沖擴散動畫實現(xiàn):
這個比較簡單仑氛,參考網(wǎng)上的好多雷達掃描實現(xiàn)乙埃,PulsingView.m文件中 代碼如下:

    [super drawRect:rect];
    [[UIColor whiteColor] setFill];
    UIRectFill(rect);
    
    UIImage * image = [UIImage imageNamed:@"radar_background"];
    [image drawInRect:rect];
    
    CGFloat pulsingWidth = rect.size.width / 2.5;
    CGFloat pulsingX = self.center.x - pulsingWidth * 0.5;
    CGFloat pulsingY = self.center.y - pulsingWidth * 0.5;
   
 // 脈沖layer
    CALayer * pulsingLayer = [CALayer layer];
    pulsingLayer.frame = CGRectMake(pulsingX, pulsingY, pulsingWidth, pulsingWidth);
    pulsingLayer.borderColor = [UIColor colorWithRed:201/255.0 green:201/255.0 blue:201/255.0 alpha:1].CGColor;
    pulsingLayer.cornerRadius = pulsingWidth * 0.5;
    pulsingLayer.backgroundColor = [UIColor whiteColor].CGColor;//這里必須設(shè)置layer層的背景顏色,默認應(yīng)該是透明的调衰,導(dǎo)致設(shè)置的陰影顏色無法顯示出來
    pulsingLayer.shadowColor = [UIColor blackColor].CGColor;
    pulsingLayer.shadowOffset = CGSizeMake(0, 0);
    pulsingLayer.shadowOpacity = 1;
    pulsingLayer.shadowRadius = 5;
    [self.layer addSublayer:pulsingLayer];
    
    // 縮放動畫
    CABasicAnimation * scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.autoreverses = false;
    scaleAnimation.fromValue = @1.0f;
    scaleAnimation.toValue = @2.0f;
    
    // 透明動畫
    CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    opacityAnimation.keyTimes = @[@0,@0.1,@0.2,@0.3,@0.4,@0.5,@0.6,@0.7,@0.8,@0.9,@1];
    opacityAnimation.values = @[@1,@0.9,@0.8,@0.7,@0.6,@0.5,@0.4,@0.3,@0.2,@0.1,@0];
    
    CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
    animationGroup.beginTime = CACurrentMediaTime() + 1;
    animationGroup.fillMode = kCAFillModeBackwards;
    animationGroup.repeatCount = HUGE_VAL;
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animationGroup.duration = 2;
    animationGroup.animations = @[scaleAnimation,opacityAnimation];
    [pulsingLayer addAnimation:animationGroup forKey:@"pulse"];

這一步做完會出來如下效果:

hhhh1.gif

接下來就是添加雷達的內(nèi)圈layer,繼續(xù)在上面的代碼下面添加如下代碼:

    // 中間圓環(huán)
    CALayer * middleCycle = [CALayer layer];
    middleCycle.frame = CGRectMake(pulsingX, pulsingY, pulsingWidth, pulsingWidth);
    middleCycle.cornerRadius = pulsingWidth * 0.5;
    middleCycle.borderColor = [UIColor colorWithRed:41/255.0 green:152/255.0 blue:241/255.0 alpha:1].CGColor;
    middleCycle.backgroundColor = [UIColor whiteColor].CGColor;
    middleCycle.shadowOffset = CGSizeMake(0, 0);
    middleCycle.borderWidth = 1;
    middleCycle.shadowRadius = 3;
    middleCycle.shadowOpacity = 1;
    middleCycle.shadowColor = [UIColor lightGrayColor].CGColor;
    [self.layer addSublayer:middleCycle];

膊爪。這里的坑也是出現(xiàn)在這塊地方。因為在外部引用PulsingView的時候嚎莉,設(shè)置的frame是控制器viewbounds,此時運行出來的結(jié)果如下:

middleCycle.gif

接下來就是最后一步米酬,添加扇形的layer 并添加掃描動畫(一開始扇形是打算做成漸變的效果的,不過這里沒有完美實現(xiàn)出來趋箩,一開始使用了一個三方XHRadarView,單純的引用里面的扇形view的類赃额,這樣就可以直接使用他內(nèi)部的漸變color,不過出來并不是很完美叫确,所以還是自己畫扇形跳芳,先不做漸變效果了。)此時就出現(xiàn)了關(guān)于position問題導(dǎo)致的坑.
這里一開的思路還是和之前一樣竹勉,繼續(xù)在self.layer上添加扇形的layer飞盆,以self.center為圓心,畫一個90度的曲線:

  CGPoint fanshapedCenter = self.center;
    UIBezierPath * fanshapedPath = [UIBezierPath bezierPath];
    [fanshapedPath addArcWithCenter:fanshapedCenter radius:(pulsingWidth + 20) * 0.5 startAngle:3 * M_PI / 2 endAngle:0 clockwise:YES];
    [fanshapedPath addLineToPoint:fanshapedCenter];
    [fanshapedPath closePath];
    CAShapeLayer * fanshapedLayer = [CAShapeLayer layer];
    fanshapedLayer.path = fanshapedPath.CGPath;
    fanshapedLayer.opacity = 0.7;
    fanshapedLayer.fillColor = [UIColor colorWithRed:41/255.0 green:152/255.0 blue:241/255.0 alpha:1].CGColor;
    [self.layer addSublayer:fanshapedLayer];

此時運行出來靜態(tài)情況下的都沒問題:

middleCyclestatic.gif

然后添加旋轉(zhuǎn)動畫次乓,讓扇形繞著圓心進行自轉(zhuǎn):

  CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: 3 * M_PI ];
    rotationAnimation.duration = 8;
    rotationAnimation.cumulative = YES;
    rotationAnimation.removedOnCompletion = NO;
    rotationAnimation.repeatCount = MAXFLOAT;
    rotationAnimation.fillMode = kCAFillModeForwards;
    [fanshapedLayer addAnimation:rotationAnimation forKey:@"rotation"];

然而運行出來的結(jié)果并沒有和我們預(yù)期的一樣:

middleCycle.gif

仔細觀察可以發(fā)現(xiàn)吓歇,扇形是在圍繞著self的原點(0,0)點進行公轉(zhuǎn),一開始一直以為是畫扇形的時候出的問題票腰,是不是畫法不對之類的城看,還試過直接用Quaritz2D 去畫扇形,然而效果依然如此杏慰,經(jīng)過各種查找测柠,才發(fā)現(xiàn)是position 導(dǎo)致的問題,通過斷點缘滥,打印一下hanshapedLayer可以看到如下信息:

Printing description of fanshapedLayer:
<CAShapeLayer:0x608000233640; position = CGPoint (0 0); bounds = CGRect (0 0; 0 0); allowsGroupOpacity = YES; fillColor = <CGColor 0x6080000bef00> [<CGColorSpace 0x600000228940> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 0.160784 0.596078 0.945098 1 ); opacity = 0.7; path = <CGPath 0x60800003bf20>>

可以看到hanshapedLayer的position 是 (0,0),也就是父控件的左上角原點轰胁,文章開頭我們提到過,layer的position 就是自己anchorPoint 相對于父layer 的坐標朝扼,而layer自身旋轉(zhuǎn)也是相對于anchorPoint 旋轉(zhuǎn)软吐,這也就解釋了為什么我們上面會出現(xiàn)扇形繞著屏幕的最上角做公轉(zhuǎn)。所以我們就需要將hanshapedLayer 的 position 移到中心點的位置:

    fanshapedLayer.position = fanshapedCenter;

此時我們再來看運行結(jié)果:

middleCycle.gif

此時扇形確實是繞著中心點開始轉(zhuǎn)了吟税,但是并不是我們想要的結(jié)果凹耙。姿现。。此時內(nèi)心是崩潰的肖抱。所以放棄了這種動畫的方式备典,直接將扇形fanshapedLayer添加到中間的內(nèi)圈layer上,然后讓內(nèi)圈layer自轉(zhuǎn)
意述,最后可以實現(xiàn)最終的效果提佣。

// 掃描的扇形
     UIBezierPath * fanshapedPath = [UIBezierPath bezierPath];
     [fanshapedPath addArcWithCenter:CGPointMake(middleCycle.frame.size.width * 0.5, middleCycle.frame.size.height * 0.5) radius:(pulsingWidth + 30) * 0.5 startAngle:3 * M_PI / 2 endAngle:0 clockwise:YES];
     [fanshapedPath addLineToPoint:CGPointMake(middleCycle.frame.size.width * 0.5, middleCycle.frame.size.height * 0.5)];
     CAShapeLayer * fanshaped = [CAShapeLayer layer];
     fanshaped.fillColor = [UIColor colorWithRed:41/255.0 green:152/255.0 blue:241/255.0 alpha:1].CGColor;
     fanshaped.opacity = 0.7;
     [fanshapedPath closePath];
     fanshaped.path = fanshapedPath.CGPath;
     [middleCycle addSublayer:fanshaped];

然后將動畫添加到middleCycle上:
     [middleCycle addAnimation:rotationAnimation forKey:@"rotation"];

后來在簡書上又看到以篇博客也遇到了公轉(zhuǎn)的問題 CALayer旋轉(zhuǎn)動畫
參考這位 渣孩子博主的作法,將畫扇形的代碼作如下修改:

   [fanshapedPath addArcWithCenter:CGPointZero radius:(pulsingWidth + 20) * 0.5 startAngle:3 * M_PI / 2 endAngle:0 clockwise:YES];
    [fanshapedPath addLineToPoint:CGPointZero];

現(xiàn)在原點位置畫出扇形荤崇,然后再設(shè)置potisionfanshapedLayer.position = fanshapedCenter;最后終于解決了這個問題拌屏。

最后,貼上draw 方法里的全部代碼:
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
    [super drawRect:rect];
    [[UIColor whiteColor] setFill];
    UIRectFill(rect);
    
    UIImage * image = [UIImage imageNamed:@"radar_background"];
    [image drawInRect:rect];
    
    CGFloat pulsingWidth = rect.size.width / 2.5;
    CGFloat pulsingX = self.center.x - pulsingWidth * 0.5;
    CGFloat pulsingY = self.center.y - pulsingWidth * 0.5;
    // 脈沖layer
    CALayer * pulsingLayer = [CALayer layer];
    pulsingLayer.frame = CGRectMake(pulsingX, pulsingY, pulsingWidth, pulsingWidth);
    pulsingLayer.borderColor = [UIColor colorWithRed:201/255.0 green:201/255.0 blue:201/255.0 alpha:1].CGColor;
    pulsingLayer.cornerRadius = pulsingWidth * 0.5;
    pulsingLayer.backgroundColor = [UIColor whiteColor].CGColor;//這里必須設(shè)置layer層的背景顏色术荤,默認應(yīng)該是透明的倚喂,導(dǎo)致設(shè)置的陰影顏色無法顯示出來
    pulsingLayer.shadowColor = [UIColor blackColor].CGColor;
    pulsingLayer.shadowOffset = CGSizeMake(0, 0);
    pulsingLayer.shadowOpacity = 1;
    pulsingLayer.shadowRadius = 5;
    [self.layer addSublayer:pulsingLayer];
    
    // 縮放動畫
    CABasicAnimation * scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.autoreverses = false;
    scaleAnimation.fromValue = @1.0f;
    scaleAnimation.toValue = @2.0f;
    
    // 透明動畫
    CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    opacityAnimation.keyTimes = @[@0,@0.1,@0.2,@0.3,@0.4,@0.5,@0.6,@0.7,@0.8,@0.9,@1];
    opacityAnimation.values = @[@1,@0.9,@0.8,@0.7,@0.6,@0.5,@0.4,@0.3,@0.2,@0.1,@0];
    
    CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
    animationGroup.beginTime = CACurrentMediaTime() + 1;
    animationGroup.fillMode = kCAFillModeBackwards;
    animationGroup.repeatCount = HUGE_VAL;
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animationGroup.duration = 2;
    animationGroup.animations = @[scaleAnimation,opacityAnimation];
    [pulsingLayer addAnimation:animationGroup forKey:@"pulse"];
    
    
    // 中間圓環(huán)
    CALayer * middleCycle = [CALayer layer];
    middleCycle.frame = CGRectMake(pulsingX, pulsingY, pulsingWidth, pulsingWidth);
    middleCycle.cornerRadius = pulsingWidth * 0.5;
    middleCycle.borderColor = [UIColor colorWithRed:41/255.0 green:152/255.0 blue:241/255.0 alpha:1].CGColor;
    middleCycle.backgroundColor = [UIColor whiteColor].CGColor;
    middleCycle.shadowOffset = CGSizeMake(0, 0);
    middleCycle.borderWidth = 1;
    middleCycle.shadowRadius = 3;
    middleCycle.shadowOpacity = 1;
    middleCycle.shadowColor = [UIColor lightGrayColor].CGColor;
    [self.layer addSublayer:middleCycle];
    
    
    // 添加到self.layer上
    CGPoint fanshapedCenter = self.center;
    UIBezierPath * fanshapedPath = [UIBezierPath bezierPath];
    [fanshapedPath addArcWithCenter:CGPointZero radius:(pulsingWidth + 20) * 0.5 startAngle:3 * M_PI / 2 endAngle:0 clockwise:YES];
    [fanshapedPath addLineToPoint:CGPointZero];
    [fanshapedPath closePath];
    CAShapeLayer * fanshapedLayer = [CAShapeLayer layer];
    fanshapedLayer.path = fanshapedPath.CGPath;
    fanshapedLayer.opacity = 0.7;
    fanshapedLayer.position = fanshapedCenter;
    fanshapedLayer.fillColor = [UIColor colorWithRed:41/255.0 green:152/255.0 blue:241/255.0 alpha:1].CGColor;
    [self.layer addSublayer:fanshapedLayer];
  
    // 添加到middleCycle上
//    [fanshapedPath addArcWithCenter:CGPointMake(0,0) radius:(pulsingWidth + 20) * 0.5 startAngle:3 * M_PI / 2 endAngle:0 clockwise:YES];
//    [fanshapedPath addLineToPoint:CGPointZero];
//    CAShapeLayer * fanshaped = [CAShapeLayer layer];
//    fanshaped.fillColor = [UIColor colorWithRed:41/255.0 green:152/255.0 blue:241/255.0 alpha:1].CGColor;
//    fanshaped.opacity = 0.7;
//    fanshaped.position = CGPointMake(middleCycle.frame.size.width * 0.5, middleCycle.frame.size.height * 0.5);
//    [fanshapedPath closePath];
//    fanshaped.path = fanshapedPath.CGPath;
//    [middleCycle addSublayer:fanshaped];
//    NSLog(@"fanshaped==== frame:%@,anchorPoint:%@,bounds:%@,position:%@",NSStringFromCGRect(fanshaped.frame),NSStringFromCGPoint(fanshaped.anchorPoint),NSStringFromCGRect(fanshaped.bounds),NSStringFromCGPoint(fanshaped.position));
 
    
    CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: 3 * M_PI ];
    rotationAnimation.duration = 8;
    rotationAnimation.cumulative = YES;
    rotationAnimation.removedOnCompletion = NO;
    rotationAnimation.repeatCount = MAXFLOAT;
    rotationAnimation.fillMode = kCAFillModeForwards;
    //    [middleCycle addAnimation:rotationAnimation forKey:@"rotation"];

    [fanshapedLayer addAnimation:rotationAnimation forKey:@"rotation"];
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瓣戚,隨后出現(xiàn)的幾起案子端圈,更是在濱河造成了極大的恐慌,老刑警劉巖子库,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舱权,死亡現(xiàn)場離奇詭異,居然都是意外死亡仑嗅,警方通過查閱死者的電腦和手機宴倍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仓技,“玉大人鸵贬,你說我怎么就攤上這事』胝茫” “怎么了恭理?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵拯辙,是天一觀的道長郭变。 經(jīng)常有香客問我,道長涯保,這世上最難降的妖魔是什么诉濒? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮夕春,結(jié)果婚禮上未荒,老公的妹妹穿的比我還像新娘。我一直安慰自己及志,他們只是感情好片排,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布寨腔。 她就那樣靜靜地躺著,像睡著了一般率寡。 火紅的嫁衣襯著肌膚如雪迫卢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天冶共,我揣著相機與錄音乾蛤,去河邊找鬼。 笑死捅僵,一個胖子當著我的面吹牛家卖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庙楚,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼上荡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了醋奠?” 一聲冷哼從身側(cè)響起榛臼,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窜司,沒想到半個月后沛善,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡塞祈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年金刁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片议薪。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡尤蛮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斯议,到底是詐尸還是另有隱情产捞,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布哼御,位于F島的核電站坯临,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏恋昼。R本人自食惡果不足惜看靠,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望液肌。 院中可真熱鬧挟炬,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粥喜,卻和暖如春空幻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背容客。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工秕铛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缩挑。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓但两,卻偏偏與公主長得像,于是被迫代替她去往敵國和親供置。 傳聞我的和親對象是個殘疾皇子谨湘,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜芥丧,今天將帶大家一窺ios動畫全貌紧阔。在這里你可以看...
    每天刷兩次牙閱讀 8,515評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜续担,今天將帶大家一窺iOS動畫全貌擅耽。在這里你可以看...
    F麥子閱讀 5,116評論 5 13
  • 轉(zhuǎn)載:http://www.reibang.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,224評論 0 13
  • 在iOS實際開發(fā)中常用的動畫無非是以下四種:UIView動畫,核心動畫物遇,幀動畫乖仇,自定義轉(zhuǎn)場動畫。 1.UIView...
    請叫我周小帥閱讀 3,114評論 1 23
  • 概覽 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜诗舰,今天將帶大家一窺iOS動畫全貌警儒。在這里你...
    被吹落的風閱讀 1,568評論 1 2