Ich möchte eine benutzerdefinierte UIView-Unterklasse erstellen, die eine Reihe von Sternen an einem dunkelblauen Himmel darstellt.Benutzerdefinierte UIView: animiere SubLayers mit Verzögerung
Deshalb habe ich diese Ansicht:
import UIKit
class ConstellationView: UIView {
// MARK: - Properties
@IBInspectable var numberOfStars: Int = 80
@IBInspectable var animated: Bool = false
// Private properties
private var starsToDraw = [CAShapeLayer]()
// Layers
private let starsLayer = CAShapeLayer()
// MARK: - Drawing
// override func drawRect(rect: CGRect) {
override func layoutSubviews() {
// Generate stars
drawStars(rect: self.bounds)
}
/// Generate stars
func drawStars(rect: CGRect) {
let width = rect.size.width
let height = rect.size.height
let screenBounds = UIScreen.main.bounds
// Create the stars and store them in starsToDraw array
for _ in 0 ..< numberOfStars {
let x = randomFloat() * width
let y = randomFloat() * height
// Calculate the thinness of the stars as a percentage of the screen resolution
let thin: CGFloat = max(screenBounds.width, screenBounds.height) * 0.003 * randomFloat()
let starLayer = CAShapeLayer()
starLayer.path = UIBezierPath(ovalIn: CGRect(x: x, y: y, width: thin, height: thin)).cgPath
starLayer.fillColor = UIColor.white.cgColor
starsToDraw.append(starLayer)
}
// Define a fade animation
let appearAnimation = CABasicAnimation(keyPath: "opacity")
appearAnimation.fromValue = 0.2
appearAnimation.toValue = 1
appearAnimation.duration = 1
appearAnimation.fillMode = kCAFillModeForwards
// Add the animation to each star (if animated)
for (index, star) in starsToDraw.enumerated() {
if animated {
// Add 1 s between each animation
appearAnimation.beginTime = CACurrentMediaTime() + TimeInterval(index)
star.add(appearAnimation, forKey: nil)
}
starsLayer.insertSublayer(star, at: 0)
}
// Add the stars layer to the view layer
layer.insertSublayer(starsLayer, at: 0)
}
private func randomFloat() -> CGFloat {
return CGFloat(arc4random())/CGFloat(UINT32_MAX)
}
}
Es funktioniert ganz gut, hier ist das Ergebnis:
aber ich möchte es animiert haben, das heißt, jeder der 80 Sterne sollte nacheinander mit einer Verzögerung von 1 Sekunde erscheinen.
Ich habe versucht, die beginTime
meiner Animation zu erhöhen, aber es scheint nicht den Trick zu tun. Ich habe mit drawRect
oder layoutSubviews
überprüft, aber es gibt keinen Unterschied.
Können Sie mir helfen?
Dank
PS: meine App reproduzieren, erstellen Sie einfach eine neue Single View-App in XCode, eine neue Datei mit diesem Code erstellen, und legen Sie die Ansicht des Viewcontroller als ConstellationView, mit einem dunklen Hintergrundfarbe. Setzen Sie die Eigenschaft animated
auch auf true, entweder im Interface Builder oder im Code.
PPS: Das ist in Swift 3, aber ich denke, es
Guter Fang ! Der Trick war 'kCAFillModeBackwards'. Der Animationsschlüssel spielt hier keine Rolle, da er nur dazu dient, eine Animation nach dem Start zu identifizieren (wenn Sie sie später "fangen" wollen). –
Warten 4 Stunden, um das Kopfgeld zu vergeben ... –