Animation du noyau iPhone - tracer un cercle

je souhaite créer une animation. La meilleure façon d'expliquer cela est si vous pouvez imaginer dessiner un cercle. Il commence en haut ou 12 o horloge et dessine dans le sens des aiguilles d'une montre tout autour jusqu'à ce qu'il devienne un cercle complet sur l'espace d'environ 10 Secondes.

le placard où j'en suis est de dessiner un point tournant autour d'un point central en utilisant L'Animation de base (en utilisant le code échantillon ici ). Mais je ne sais pas comment dessiner le cercle? Tout des suggestions sont les bienvenues.

Merci Beaucoup :)

48
demandé sur bennythemink 2011-11-03 10:37:36

4 réponses

ce que vous devez vraiment faire est de animer la course d'un joueur de Cashapel où le chemin est un cercle. Cela sera accéléré en utilisant L'Animation de base et est moins salissant que de dessiner une partie d'un cercle dans-drawRect:.

le code ci-dessous va créer une couche de forme de cercle au centre de l'écran et animer la course de celui-ci dans le sens des aiguilles d'une montre de sorte qu'il semble si elle est dessinée. Vous pouvez bien sûr utiliser la forme que vous voulez. (Vous pouvez lire cet article sur Ole Begemanns blog pour en savoir plus sur la façon d'animer le coup d'une couche de forme.)

Note: les propriétés stoke ne sont pas les mêmes que les propriétés de bordure sur la couche. Pour changer la largeur de la course, vous devez utiliser "lineWidth" au lieu de "borderWitdh" etc.

// Set up the shape of the circle
int radius = 100;
CAShapeLayer *circle = [CAShapeLayer layer];
// Make a circular shape
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) 
                                         cornerRadius:radius].CGPath;
// Center the shape in self.view
circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius, 
                              CGRectGetMidY(self.view.frame)-radius);

// Configure the apperence of the circle
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blackColor].CGColor;
circle.lineWidth = 5;

// Add to parent layer
[self.view.layer addSublayer:circle];

// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration            = 10.0; // "animate over 10 seconds or so.."
drawAnimation.repeatCount         = 1.0;  // Animate only once..

// Animate from no part of the stroke being drawn to the entire stroke being drawn
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue   = [NSNumber numberWithFloat:1.0f];

// Experiment with timing to get the appearence to look the way you want
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

// Add the animation to the circle
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
160
répondu David Rönnqvist 2014-02-02 22:48:07

Voici une autre solution au problème, basée sur la réponse de @David. Cette approche vous permet de définir la direction de l'animation du cercle, et offre un peu plus de contrôle. Edit: j'ai écrit un billet de blog sur comment dessiner un cercle avec Swift , que je vais essayer de garder à jour avec les bêtas. Vérifier si le code ci-dessous ne fonctionne pas pour vous.

let radius = 100.0

// Create the circle layer
var circle = CAShapeLayer()

// Set the center of the circle to be the center of the view
let center = CGPointMake(CGRectGetMidX(self.frame) - radius, CGRectGetMidY(self.frame) - radius)

let fractionOfCircle = 3.0 / 4.0

let twoPi = 2.0 * Double(M_PI)
// The starting angle is given by the fraction of the circle that the point is at, divided by 2 * Pi and less
// We subtract M_PI_2 to rotate the circle 90 degrees to make it more intuitive (i.e. like a clock face with zero at the top, 1/4 at RHS, 1/2 at bottom, etc.)
let startAngle = Double(fractionOfCircle) / Double(twoPi) - Double(M_PI_2)
let endAngle = 0.0 - Double(M_PI_2)
let clockwise: Bool = true

// `clockwise` tells the circle whether to animate in a clockwise or anti clockwise direction
circle.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: clockwise).CGPath

// Configure the circle
circle.fillColor = UIColor.blackColor().CGColor
circle.strokeColor = UIColor.redColor().CGColor
circle.lineWidth = 5

// When it gets to the end of its animation, leave it at 0% stroke filled
circle.strokeEnd = 0.0

// Add the circle to the parent layer
self.layer.addSublayer(circle)

// Configure the animation
var drawAnimation = CABasicAnimation(keyPath: "strokeEnd")
drawAnimation.repeatCount = 1.0

// Animate from the full stroke being drawn to none of the stroke being drawn
drawAnimation.fromValue = NSNumber(double: fractionOfCircle)
drawAnimation.toValue = NSNumber(float: 0.0)

drawAnimation.duration = 30.0

drawAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)

// Add the animation to the circle
circle.addAnimation(drawAnimation, forKey: "drawCircleAnimation")
8
répondu matthewpalmer 2014-08-17 01:19:11

j'ai une solution à ce problème, code ci-dessous. Il semble que j'ai foiré dans mon explication du problème à la main donc réécrit comme une autre question qui a reçu une réponse avec la bonne solution, voir ici

merci à tous pour leurs conseils!

-(void)drawRect:(CGRect)rect
{
    // Drawing code

    CGRect allRect = self.bounds;
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Draw background
    CGContextSetRGBStrokeColor(context, self.strokeValueRed, self.strokeValueGreen, self.strokeValueBlue, self.strokeValueAlpha); // white
    CGContextSetLineWidth(context, 5);

    // Draw progress
    CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2);
    CGFloat radius = (allRect.size.width - 4) / 2;
    CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees
    CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle;
    CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
    CGContextStrokePath(context);
}
3
répondu bennythemink 2017-05-23 11:46:08

Ok j'ai une correction partielle. J'ai trouvé le code suivant qui dessine les segments d'un cercle. Son fondamentalement une sous-classe UIView qui obtient son drawRect tiré chaque fois que sa progression devrait être mis à jour. La seule question que j'ai maintenant est comment je le changerais pour qu'au lieu de dessiner des sections ou des tranches il dessine juste le trait de cercle?

-(void)drawRect:(CGRect)rect 
{
    // Drawing code

    CGRect allRect = self.bounds;
    CGRect circleRect = CGRectInset(allRect, 2.0f, 2.0f);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Draw background
    CGContextSetRGBStrokeColor(context, self.strokeValueRed, self.strokeValueGreen, self.strokeValueBlue, self.strokeValueAlpha); // white
    CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 0.1f); // translucent white
    CGContextSetLineWidth(context, self.lineWidth);
    CGContextFillEllipseInRect(context, circleRect);
    CGContextStrokeEllipseInRect(context, circleRect);

    // Draw progress
    CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2);
    CGFloat radius = (allRect.size.width - 4) / 2;
    CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees
    CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle;
    CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); // white
    CGContextMoveToPoint(context, center.x, center.y);
    CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
    CGContextClosePath(context);
    CGContextFillPath(context);
}
0
répondu bennythemink 2013-09-10 13:16:20