Je cherche un moyen d'animer le dessin d'un cercle. J'ai pu créer le cercle, mais il le rassemble.
Voici ma 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'ajoute à la hiérarchie de vues dans mon contrôleur de vue:
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)
}
Existe-t-il un moyen d'animer le dessin du cercle sur 1 seconde?
Exemple, à mi-parcours de l'animation, cela ressemblerait à la ligne bleue de cette image:
Réponses:
Le moyen le plus simple de le faire est d'utiliser la puissance de l'animation de base pour faire la plupart du travail à votre place. Pour ce faire, nous devrons déplacer votre code de dessin de cercle de votre
drawRect
fonction vers un fichierCAShapeLayer
. Ensuite, nous pouvons utiliser aCABasicAnimation
pour animerCAShapeLayer
lastrokeEnd
propriété de0.0
à1.0
.strokeEnd
est une grande partie de la magie ici; à partir de la documentation:Si nous nous fixons
strokeEnd
à0.0
, cela ne dessinera rien. Si nous le réglons sur1.0
, cela dessinera un cercle complet. Si nous le réglons sur0.5
, il dessinera un demi-cercle. etc.Donc, pour commencer, permet de créer un
CAShapeLayer
dans votreCircleView
deinit
fonction et d' ajouter cette couche à la vue desublayers
(aussi être sûr d'enlever ladrawRect
fonction puisque la couche sera dessiner le cercle maintenant):Remarque: nous sommes en train de configurer
circleLayer.strokeEnd = 0.0
le cercle pour que le cercle ne soit pas dessiné tout de suite.Maintenant, ajoutons une fonction que nous pouvons appeler pour déclencher l'animation du cercle:
Ensuite, tout ce que nous avons à faire est de changer votre
addCircleView
fonction pour qu'elle déclenche l'animation lorsque vous ajoutez leCircleView
à sonsuperview
:Tout ce qui est assemblé devrait ressembler à ceci:
Remarque: il ne se répétera pas comme ça, il restera un cercle complet après son animation.
la source
strokeEnd
self.view?.layer.addSublayer(circleLayer)
:-)startAngle:
etendAngle:
duUIBezierPath
.0
est la position 3, donc la position 12 serait inférieure de 90 ° à celle, qui est -π / 2 en radians. Ainsi, les paramètres seraientstartAngle: 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 dessiné, c'est pourquoi vous soustrayez un très très petit décalage austartAngle
Réponse Mikes mise à jour pour Swift 3.0
Pour appeler la fonction:
la source
M_PI
est obsolète - utilisez à laCGFloat.pi
place.La réponse de Mike est géniale! Un autre moyen simple et agréable de le faire est d'utiliser drawRect combiné avec setNeedsDisplay (). Cela semble lent, mais ce n'est pas :-)
Nous voulons dessiner un cercle partant du haut, qui fait -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, allant de minAngle (-90) à maxAngle (270).
Dans drawRect, nous spécifions comment le cercle est censé s'afficher:
Le problème est que pour le moment, comme currentAngle ne change pas, le cercle est statique et ne s'affiche même pas, comme currentAngle = minAngle.
Nous créons ensuite une minuterie, et chaque fois que cette minuterie se déclenche, nous augmentons currentAngle. En haut de votre classe, ajoutez le temps entre deux incendies:
Dans votre init, ajoutez le timer:
Nous pouvons ajouter la fonction qui sera appelée lorsque la minuterie se déclenchera:
Malheureusement, lors de l'exécution de l'application, rien ne s'affiche car nous n'avons pas spécifié le système à dessiner à nouveau. Cela se fait en appelant setNeedsDisplay (). Voici la fonction de minuterie mise à jour:
_ _ _
Tout le code dont vous avez besoin est résumé ici:
Si vous souhaitez changer la vitesse, modifiez simplement la fonction updateTimer, ou la vitesse à laquelle cette fonction est appelée. De plus, vous voudrez peut-être invalider le minuteur une fois le cercle terminé, ce que j'ai oublié de faire :-)
NB: Pour ajouter le cercle dans votre storyboard, il suffit d'ajouter une vue, de la sélectionner, d'aller dans son inspecteur d'identité , et en tant que classe , de spécifier CircleClosing .
À votre santé! bRo
la source
Si vous voulez un gestionnaire de complétion, c'est une autre solution similaire à celle de Mike S, réalisée dans Swift 3.0
Avec le gestionnaire de complétion, vous pouvez réexécuter l'animation soit en appelant récursivement la même fonction pour refaire l'animation (ce qui ne sera pas très joli), ou vous pouvez avoir une fonction inversée qui enchaînera continuellement jusqu'à ce qu'une condition soit remplie , par exemple:
Pour le rendre encore plus sophistiqué, vous pouvez changer la direction de l'animation comme ceci:
la source
Non seulement vous pouvez sous-classer un
UIView
, vous pouvez aussi aller un peu plus loin, sous-classer unCALayer
En d'autres termes, strokeEnd de CoreAnimation est OK. Pour appeler le dessin de CALayer (en ctx :) fréquemment est également OK
et la casquette ronde est belle
Le point clé est de remplacer la méthode de CALayer
action(forKey:)
La sous-classe interne de CAShapeLayer
méthodes d'assistance
utiliser une sous-classe UIView, avec le CALayer personnalisé interne
Usage:
avec une image indicatrice pour régler l'angle
la source
mise à jour de la réponse de @Mike S pour Swift 5
fonctionne pour
frame manually
、storyboard setup
、autolayout setup
Utilisation:
exemple de code pour
frame manually
、storyboard setup
、autolayout setup
la source