2015-05-17 125 views
1

我想向我的應用程序添加一個倒計時,並且在動畫時遇到問題。我所看到的外觀與下面顯示的iPad倒計時類似,紅色條隨着時鐘倒數而增加。 enter image description here如何爲倒數計時器創建一個循環進度指示器

起初,我創建了一個影像地圖集以倒計時的每半秒鐘一個單獨的圖像但這似乎需要大量的內存來運行,因此崩潰的應用程序,所以我現在必須找到一種替代方法。

我一直在尋找着色這裏https://developer.apple.com/library/prerelease/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Sprites/Sprites.html#//apple_ref/doc/uid/TP40013043-CH9,但看不到一種顏色的部分精靈的方式,似乎整個精靈會改變。

有沒有人知道在這裏着色會是一個選擇,還是有減少圖像地圖集使用的內存的方法?

感謝

+1

是否有你需要SpriteKit這樣做的一個原因?通常,您可以通過在CAShapeLayer中將UIBezierPath的strokeEnd屬性動畫化來實現此目的。 – rdelmar

+0

SpriteKit除此之外沒有任何理由用於遊戲的其餘部分,並開始尋找能否讓計時器工作。還沒有使用貝塞爾路徑,但會考慮到這一點。謝謝你的幫助。 – user1759949

回答

12

則可以使用CAShapeLayer和動畫行程結束如下操作:

更新的Xcode 9•斯威夫特4

定義時間留給

let timeLeftShapeLayer = CAShapeLayer() 
let bgShapeLayer = CAShapeLayer() 
var timeLeft: TimeInterval = 60 
var endTime: Date? 
var timeLabel = UILabel() 
var timer = Timer() 
// here you create your basic animation object to animate the strokeEnd 
let strokeIt = CABasicAnimation(keyPath: "strokeEnd") 

定義一種方法來創建de UIBezierPath

由startAngle在-90˚和endAngle 270

func drawBgShape() { 
    bgShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: view.frame.midX , y: view.frame.midY), radius: 
     100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath 
    bgShapeLayer.strokeColor = UIColor.white.cgColor 
    bgShapeLayer.fillColor = UIColor.clear.cgColor 
    bgShapeLayer.lineWidth = 15 
    view.layer.addSublayer(bgShapeLayer) 
} 
func drawTimeLeftShape() { 
    timeLeftShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: view.frame.midX , y: view.frame.midY), radius: 
     100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath 
    timeLeftShapeLayer.strokeColor = UIColor.red.cgColor 
    timeLeftShapeLayer.fillColor = UIColor.clear.cgColor 
    timeLeftShapeLayer.lineWidth = 15 
    view.layer.addSublayer(timeLeftShapeLayer) 
} 

添加標籤

func addTimeLabel() { 
    timeLabel = UILabel(frame: CGRect(x: view.frame.midX-50 ,y: view.frame.midY-25, width: 100, height: 50)) 
    timeLabel.textAlignment = .center 
    timeLabel.text = timeLeft.time 
    view.addSubview(timeLabel) 
} 

在viewDidLoad中設定的結束時間和你CAShapeLayer添加到您的視圖:

override func viewDidLoad() { 
    super.viewDidLoad() 
    view.backgroundColor = UIColor(white: 0.94, alpha: 1.0) 
    drawBgShape() 
    drawTimeLeftShape() 
    addTimeLabel() 
    // here you define the fromValue, toValue and duration of your animation 
    strokeIt.fromValue = 0 
    strokeIt.toValue = 1 
    strokeIt.duration = 60 
    // add the animation to your timeLeftShapeLayer 
    timeLeftShapeLayer.add(strokeIt, forKey: nil) 
    // define the future end time by adding the timeLeft to now Date() 
    endTime = Date().addingTimeInterval(timeLeft) 
    timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true) 
} 
更新時

時間

@objc func updateTime() { 
    if timeLeft > 0 { 
     timeLeft = endTime?.timeIntervalSinceNow ?? 0 
     timeLabel.text = timeLeft.time 
    } else { 
     timeLabel.text = "00:00" 
     timer.invalidate() 
    } 
} 

您可以使用此擴展度轉換爲弧度和顯示時間

extension TimeInterval { 
    var time: String { 
     return String(format:"%02d:%02d", Int(self/60), Int(ceil(truncatingRemainder(dividingBy: 60)))) 
    } 
} 
extension Int { 
    var degreesToRadians : CGFloat { 
     return CGFloat(self) * .pi/180 
    } 
} 

Sample project

+0

感謝您的幫助。 – user1759949

+0

再次感謝,這完美的作品。你知道如何確保形狀圖層保留在後面,以便拖動它的任何精靈節點都會顯示在最上面?我試過設置zposition,但是這在shapelayer和節點之間似乎不起作用。 – user1759949

+0

我會嘗試使用SK來做它,並會讓你知道 –

0

大的代碼並回答!只是想我會建議以下。我將時間顯示爲1:00然後0:60,我認爲這可能是由於代碼的「ceil」部分。

我把它改成下面的樣子(同樣希望小於60的時候顯示不同),它似乎已經消除了時間的重疊。

對於它的價值......

extension NSTimeInterval { 
    var time:String { 
     if self < 60 { 
      return String(format: "%02d", Int(floor(self%60))) 
     } else 
     { 
      return String(format: "%01d:%02d", Int(self/60), Int(floor(self%60))) 
     } 
    } 
}