Ich suche nach einer Möglichkeit, die Zeichnung eines Kreises zu animieren. Ich konnte den Kreis erstellen, aber er zeichnet alles zusammen.
Hier ist meine CircleView
Klasse:
import UIKit
class CircleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(rect: CGRect) {
// Get the Graphics Context
var context = UIGraphicsGetCurrentContext();
// Set the circle outerline-width
CGContextSetLineWidth(context, 5.0);
// Set the circle outerline-colour
UIColor.redColor().set()
// Create Circle
CGContextAddArc(context, (frame.size.width)/2, frame.size.height/2, (frame.size.width - 10)/2, 0.0, CGFloat(M_PI * 2.0), 1)
// Draw
CGContextStrokePath(context);
}
}
Und so füge ich es der Ansichtshierarchie in meinem Ansichts-Controller hinzu:
func addCircleView() {
let diceRoll = CGFloat(Int(arc4random_uniform(7))*50)
var circleWidth = CGFloat(200)
var circleHeight = circleWidth
// Create a new CircleView
var circleView = CircleView(frame: CGRectMake(diceRoll, 0, circleWidth, circleHeight))
view.addSubview(circleView)
}
Gibt es eine Möglichkeit, die Zeichnung des Kreises über 1 Sekunde zu animieren?
Beispiel: Während der Animation würde es ungefähr so aussehen wie die blaue Linie in diesem Bild:
Antworten:
Der einfachste Weg, dies zu tun, besteht darin, die Kraft der Kernanimation zu nutzen, um den größten Teil der Arbeit für Sie zu erledigen. Dazu müssen wir Ihren Kreiszeichnungscode von Ihrer
drawRect
Funktion nach a verschiebenCAShapeLayer
. Dann können wir a verwendenCABasicAnimation
, umCAShapeLayer
diestrokeEnd
Eigenschaft von0.0
bis zu animieren1.0
.strokeEnd
ist ein großer Teil der Magie hier; aus den Dokumenten:Wenn wir setzen
strokeEnd
auf0.0
, wird es nichts ziehen. Wenn wir es einstellen1.0
, wird sich der Kreis schließen. Wenn wir es einstellen0.5
, wird ein Halbkreis gezeichnet. etc.Also, um zu starten, läßt eine erstellen
CAShapeLayer
in IhrerCircleView
‚s -init
Funktion und fügen Sie diese Schicht auf die Sicht dersublayers
(auch sicher sein , das entfernendrawRect
Funktion , da die Schicht nun den Kreises seine Zeichnung):Hinweis: Wir stellen ein
circleLayer.strokeEnd = 0.0
, dass der Kreis nicht sofort gezeichnet wird.Fügen wir nun eine Funktion hinzu, die wir aufrufen können, um die Kreisanimation auszulösen:
Dann alles , was wir tun müssen , um Ihre ändern
addCircleView
Funktion , so dass es die Animation ausgelöst wird, wenn Sie das AddCircleView
seinersuperview
:Alles, was zusammen passt, sollte ungefähr so aussehen:
Hinweis: Es wird nicht so wiederholt, es bleibt ein voller Kreis, nachdem es animiert wurde.
quelle
strokeEnd
self.view?.layer.addSublayer(circleLayer)
:-)startAngle:
undendAngle:
Parameter derUIBezierPath
.0
ist die 3-Position, also wäre die 12-Position 90 ° kleiner als die, die im Bogenmaß -π / 2 ist. Die Parameter wären alsostartAngle: CGFloat(-M_PI_2), endAngle: CGFloat((M_PI * 2.0) - M_PI_2)
.startAngle: (0 - (Double.pi / 2)) + 0.00001
undendAngle: 0 - (Double.pi / 2)
. WennstartAngle
und gleichendAngle
sind, wird der Kreis nicht gezeichnet, weshalb Sie einen sehr sehr kleinen Versatz zumstartAngle
Mikes Antwort für Swift 3.0 aktualisiert
So rufen Sie die Funktion auf:
quelle
M_PI
ist veraltet -CGFloat.pi
stattdessen verwenden.Mikes Antwort ist großartig! Eine andere schöne und einfache Möglichkeit ist die Verwendung von drawRect in Kombination mit setNeedsDisplay (). Es scheint nachlässig, aber es ist nicht :-)
Wir wollen von oben beginnend einen Kreis zeichnen, der -90 ° beträgt und bei 270 ° endet. Der Mittelpunkt des Kreises ist (centerX, centerY) mit einem bestimmten Radius. CurrentAngle ist der aktuelle Winkel des Endpunkts des Kreises von minAngle (-90) bis maxAngle (270).
In drawRect geben wir an, wie der Kreis angezeigt werden soll:
Das Problem ist, dass im Moment, da sich currentAngle nicht ändert, der Kreis statisch ist und nicht einmal angezeigt wird, da currentAngle = minAngle.
Wir erstellen dann einen Timer und erhöhen jedes Mal, wenn dieser Timer ausgelöst wird, currentAngle. Fügen Sie oben in Ihrer Klasse das Timing zwischen zwei Bränden hinzu:
Fügen Sie in Ihrem Init den Timer hinzu:
Wir können die Funktion hinzufügen, die aufgerufen wird, wenn der Timer ausgelöst wird:
Leider wird beim Ausführen der App nichts angezeigt, da wir nicht angegeben haben, welches System erneut gezeichnet werden soll. Dies erfolgt durch Aufrufen von setNeedsDisplay (). Hier ist die aktualisierte Timer-Funktion:
_ _ _
Der gesamte Code, den Sie benötigen, ist hier zusammengefasst:
Wenn Sie die Geschwindigkeit ändern möchten, ändern Sie einfach die updateTimer-Funktion oder die Rate, mit der diese Funktion aufgerufen wird. Vielleicht möchten Sie auch den Timer ungültig machen, sobald der Kreis geschlossen ist, was ich vergessen habe :-)
Wichtiger Hinweis: Um den Kreis in Ihrem Storyboard hinzufügen, fügen Sie einfach einen Blick, wählen Sie es, gehen Sie zu seiner Identität Inspektor , und als Klasse , geben Sie CircleClosing .
Prost! Bruder
quelle
Wenn Sie einen Completion-Handler benötigen, ist dies eine andere Lösung, die der von Mike S in Swift 3.0 ähnelt
Mit dem Completion-Handler können Sie die Animation erneut ausführen, indem Sie entweder rekursiv dieselbe Funktion aufrufen, um die Animation erneut auszuführen (was nicht sehr gut aussieht), oder Sie können eine umgekehrte Funktion verwenden, die kontinuierlich verkettet, bis eine Bedingung erfüllt ist , zum Beispiel:
Um es noch schicker zu machen, können Sie die Richtung der Animation folgendermaßen ändern:
quelle
Nicht nur Sie können eine Unterklasse
UIView
, Sie können auch etwas tiefer gehen, eine UnterklasseCALayer
Mit anderen Worten, das StrokeEnd von CoreAnimation ist in Ordnung. Es ist auch in Ordnung, CALayers Draw (in ctx :) häufig aufzurufen
und die runde Kappe ist schön
Der entscheidende Punkt ist, die CALayer-Methode zu überschreiben
action(forKey:)
Die interne Unterklasse für CAShapeLayer
Hilfsmethoden
Verwenden Sie eine UIView-Unterklasse mit dem internen benutzerdefinierten CALayer
Verwendung:
mit einem Indikatorbild zum Einstellen des Winkels
quelle
Aktualisierung der Antwort von @Mike S für Swift 5
funktioniert für
frame manually
、storyboard setup
、autolayout setup
Verwendung :
Beispielcode für
frame manually
、storyboard setup
、autolayout setup
quelle