Animer le dessin d'un cercle
Je suis à la recherche d'un moyen d'animer le dessin d'un cercle. J'ai été en mesure de créer le cercle, mais il attire tous ensemble.
Voici mon CircleView
classe:
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);
}
}
Et voici comment je l'ajouter à la vue de la hiérarchie de mon point de vue contrôleur:
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)
}
Est-il un moyen d'animer le dessin du cercle de plus de 1 seconde?
Exemple, une partie de la route par le biais de l'animation, cela ressemblerait à quelque chose comme la ligne bleue dans cette image:
- Lorsque j'utilise la classe ci-dessus, le cercle n'est pas complètement rempli, c'est un anneau de cercle (beignet à la recherche) des idées pourquoi?
Vous devez vous connecter pour publier un commentaire.
La façon la plus simple pour ce faire est d'utiliser le pouvoir de core animation à faire la plupart du travail pour vous. Pour ce faire, nous allons avoir à déplacer votre cercle de dessin de votre code d'
drawRect
fonction à unCAShapeLayer
. Ensuite, nous pouvons utiliser uneCABasicAnimation
pour animerCAShapeLayer
'sstrokeEnd
propriété de0.0
à1.0
.strokeEnd
est une grande partie de la magie ici, de la les docs:Si l'on
strokeEnd
à0.0
, il ne sera pas dessiner n'importe quoi. Si nous avons choisi1.0
, il dessine un cercle complet. Si nous avons choisi0.5
, il va dessiner un demi-cercle. etc.Donc, pour commencer, permet de créer un
CAShapeLayer
dans votreCircleView
'sinit
fonction et d'ajouter la couche à la vue dusublayers
(assurez-vous également de supprimer ladrawRect
fonction depuis la couche de dessin le cercle maintenant):Remarque: On
circleLayer.strokeEnd = 0.0
de sorte que le cercle n'est pas dessiné tout de suite.Maintenant, permet d'ajouter une fonction que l'on peut appeler pour déclencher le cercle d'animation:
Ensuite, tout ce que nous devons faire est de changer votre
addCircleView
fonction de sorte qu'il déclenche l'animation lorsque vous ajoutez leCircleView
à sonsuperview
:Tous les qui rassemble devrait ressembler à quelque chose comme ceci:
Remarque: Il ne se répétera pas comme ça, il va rester un cercle complet après qu'il anime.
strokeEnd
self.view?.layer.addSublayer(circleLayer)
🙂startAngle:
etendAngle:
paramètres de laUIBezierPath
.0
est la 3 position, de sorte que le 12 à la position de 90° de moins que cela, qui est -π/2 radians. Ainsi, les paramètresstartAngle: CGFloat(-M_PI_2), endAngle: CGFloat((M_PI * 2.0) - M_PI_2)
.startAngle: (0 - (Double.pi / 2)) + 0.00001
etendAngle: 0 - (Double.pi / 2)
. SistartAngle
etendAngle
sont les mêmes, le cercle ne sera pas établi, ce qui est pourquoi vous soustrayez un très très léger décalage de lastartAngle
Mikes réponse mis à jour pour Swift 3.0
Pour appeler la fonction:
M_PI
est obsolète - utiliserCGFloat.pi
à la place.Réponse de Mike est grand! Une autre manière agréable et simple à faire est d'utiliser drawRect combiné avec setNeedsDisplay(). Il semble lag, mais ce n'est pas 🙂
Nous voulons dessiner un cercle en partant du haut, qui est à 90° et se termine à 270°. Le centre du cercle est (centerX, centerY), avec un rayon donné. CurrentAngle est l'angle actuel du point final du cercle, passant de minAngle (-90) à maxAngle (270).
Dans drawRect, nous indiquons comment le cercle est censé afficher :
Le problème est que maintenant, comme currentAngle est de ne pas changer, le cercle est statique, et ne s'affiche même pas, comme currentAngle = minAngle.
Nous avons ensuite créer un timer, et à chaque fois que le compte à rebours incendies, nous augmentons currentAngle. En haut de votre classe, ajouter la synchronisation entre deux feux :
Dans votre init, ajouter le minuteur :
Nous pouvons ajouter la fonction qui sera appelée lorsque le compte à rebours est déclenché :
Malheureusement, lors de l'exécution de l'application, rien ne s'affiche parce que nous n'avons pas spécifier le système qu'il doit tirer de nouveau. Ceci est fait en appelant setNeedsDisplay(). Voici la mise à jour de la fonction de minuterie :
_
_
_
Tout le code dont vous avez besoin est résumée ici :
Si vous souhaitez modifier la vitesse, juste modifier le updateTimer de la fonction, ou la vitesse à laquelle cette fonction est appelée. Aussi, vous pouvez invalider la minuterie une fois que le cercle est complet, j'ai oublié de le faire 🙂
NB: Pour ajouter le cercle dans votre scénario, il suffit d'ajouter une vue, sélectionnez-la, allez à sa Identité de l'Inspecteur, et comme Classe, spécifiez CircleClosing.
Cheers! bRo
Si vous voulez un gestionnaire d'achèvement, c'est une autre solution similaire à celle de Mike S, fait en Swift 3.0
Avec le gestionnaire d'achèvement, vous pouvez exécuter de nouveau l'animation, soit par la manière récursive d'appeler la même fonction pour faire l'animation sur nouveau (ce qui n'est pas très agréable), ou vous pouvez avoir une fonction inverse qui continue de la chaîne jusqu'à ce qu'une condition est remplie, par exemple:
Pour le rendre encore plus sophistiqué, vous pouvez changer la direction de l'animation comme ceci: