2013-11-21 44 views
17

我有一個項目,我根據設置的進度爲UIBezierPath製作動畫。 BezierPath呈圓形,位於UIView中,動畫使用CADisplayLink在drawRect中完成。簡單地說,根據設定的進度x,路徑應該徑向延伸(如果x比以前大)或收縮(如果x較小)。動畫一個循環的UIBezierPath

self.drawProgress = (self.displayLink.timestamp - self.startTime)/DURATION; 

CGFloat startAngle = -(float)M_PI_2; 
CGFloat stopAngle = ((self.x * 2*(float)M_PI) + startAngle); 
CGFloat currentEndAngle = ((self.oldX * 2*(float)M_PI) + startAngle); 
CGFloat endAngle = currentEndAngle-((currentEndAngle-stopAngle)*drawProgress); 

UIBezierPath *guideCirclePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 

這是x自我們上次更新以來收縮的情況。我遇到的問題,實際上是幾個:

  1. 形狀總是開始在45º繪製(除非我旋轉視圖)。我還沒有找到任何方法來改變這種情況,並且將startAngle設置爲-45º並沒有什麼區別,因爲它總是「彈出」到45。有什麼我可以做的,或者我不得不求助於其他繪圖方法?
  2. 有沒有其他的方法讓這些東西動起來?我已經閱讀了很多關於使用CAShapeLayer的內容,但我還沒有完全理解使用這兩種方法的實際區別(在缺點和優點方面)。如果有人可以澄清我會非常感激!

更新:我遷移代碼到CAShapeLayer代替,但我現在面臨着不同的問題。它最好與此圖像描述:

enter image description here

發生了什麼事是,當層被認爲萎縮,薄的外線仍然存在(無論運動方向)。並且當條形縮小時,除非我明確地在其上新建一個白色形狀,否則不會刪除1- x的三角形。這個代碼如下。有任何想法嗎?

UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:stopAngle clockwise:YES]; 
CAShapeLayer *circle = [CAShapeLayer layer]; 
circle.path = [circlePath CGPath]; 
circle.strokeStart = 0; 
circle.strokeEnd = 1.0*self.progress; 

// Colour and other customizations here. 

if (self.progress > self.oldProgress) { 
    drawAnimation.fromValue = @(1.0*self.oldProgress); 
    drawAnimation.toValue = @(circle.strokeEnd); 
} else { 
    drawAnimation.fromValue = @(1.0*self.oldProgress); 
    drawAnimation.toValue = @(1.0*self.progress); 
    circle.strokeEnd = 1.0*self.progress; 
} 

drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; //kCAMediaTimingFunctionEaseIn 
[circle addAnimation:drawAnimation forKey:@"strokeEnd"]; 

更新2:我熨平了大部分其他錯誤的。原來,只是我整個時間都比較傻,而且整個動畫過於複雜(更不用說到處都是乘以1,什麼?)。我做了錯誤的GIF我解決不了:

radial control glitch

任何想法?

UPDATE 3:(和閉合)。我設法通過調用

[self.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; 

擺脫錯誤的,現在一切正常,因爲它應該。感謝所有的幫助!

+0

你是否想要做類似於[this(通過增加從0到360度的線段角度創建一個完整的圓形)](http://stackoverflow.com/a/8021051/608157)? –

+0

我已經遷移到使用CAShapeLayer + CABasicAnimation,因爲似乎有更合理的選擇,部分原因是能夠使用Duncan推薦的屬性。 – hav

+0

在Swift中尋找一個好的解決方案。 – hugocarlmartin

回答

10

使用CAShapeLayer更容易和更清潔。原因是CAShapeLayer包含屬性strokeStart和strokeEnd。這些值的範圍從0(路徑的開始)到1(路徑的結束)並且是可以動畫的。

通過改變它們,你可以很容易地繪製你的圓的任何弧(或者任何路徑的任何部分)。屬性是動畫的,所以你可以創建一個增長/縮小的扇形或扇形的動畫環形。它比在DrawRect中實現代碼更容易,更高效。

+1

這實際上簡化了很多事情,我將代碼遷移到使用基於CAShapeLayer和CABasicAnimation的解決方案,所以非常感謝!但是,現在我正在經歷一個不同的怪誕...... – hav

+1

那是什麼怪事? –