Comment faire pour que mon UIBezierPath animé avec CAShapeLayer?
Je suis en train d'animer un UIBezierPath et j'ai installé un CAShapeLayer à essayer de le faire. Malheureusement, l'animation ne fonctionne pas et je ne suis pas sûr que toutes les couches sont d'avoir une incidence quelconque (comme le code est en train de faire la même chose qu'il faisait avant, j'ai eu l'couches).
Voici le code - aimerais de l'aide. Draw2D est une implémentation de UIView qui est incorporé dans un UIViewController. Le dessin qui se passe à l'intérieur de la Draw2D classe. L'appel à [_helper createDrawing... ] simplement remplit la _uipath variable avec des points.
Draw2D.h définit les propriétés suivantes:
#define defaultPointCount ((int) 25)
@property Draw2DHelper *helper;
@property drawingTypes drawingType;
@property int graphPoints;
@property UIBezierPath *uipath;
@property CALayer *animationLayer;
@property CAShapeLayer *pathLayer;
- (void)refreshRect:(CGRect)rect;
ci-dessous est la mise en œuvre effective :
//
// Draw2D.m
// Draw2D
//
// Created by Marina on 2/19/13.
// Copyright (c) 2013 Marina. All rights reserved.
//
#import "Draw2D.h"
#import"Draw2DHelper.h"
#include <stdlib.h>
#import "Foundation/Foundation.h"
#import <QuartzCore/QuartzCore.h>
int MAX_WIDTH;
int MAX_HEIGHT;
@implementation Draw2D
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//Initialization code
if (self.pathLayer != nil) {
[self.pathLayer removeFromSuperlayer];
self.pathLayer = nil;
}
self.animationLayer = [CALayer layer];
self.animationLayer.frame = self.bounds;
[self.layer addSublayer:self.animationLayer];
CAShapeLayer *l_pathLayer = [CAShapeLayer layer];
l_pathLayer.frame = self.frame;
l_pathLayer.bounds = self.bounds;
l_pathLayer.geometryFlipped = YES;
l_pathLayer.path = _uipath.CGPath;
l_pathLayer.strokeColor = [[UIColor grayColor] CGColor];
l_pathLayer.fillColor = nil;
l_pathLayer.lineWidth = 1.5f;
l_pathLayer.lineJoin = kCALineJoinBevel;
[self.animationLayer addSublayer:l_pathLayer];
self.pathLayer = l_pathLayer;
[self.layer addSublayer:l_pathLayer];
}
return self;
}
//Only override drawRect: if you perform custom drawing.
//An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect :(int) points :(drawingTypes) type //:(Boolean) initial
{
//CGRect bounds = [[UIScreen mainScreen] bounds];
CGRect appframe= [[UIScreen mainScreen] applicationFrame];
CGContextRef context = UIGraphicsGetCurrentContext();
_helper = [[Draw2DHelper alloc ] initWithBounds :appframe.size.width :appframe.size.height :type];
CGPoint startPoint = [_helper generatePoint] ;
[_uipath moveToPoint:startPoint];
[_uipath setLineWidth: 1.5];
CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGPoint center = CGPointMake(self.center.y, self.center.x) ;
[_helper createDrawing :type :_uipath :( (points>0) ? points : defaultPointCount) :center];
self.pathLayer.path = (__bridge CGPathRef)(_uipath);
[_uipath stroke];
[self startAnimation];
}
- (void) startAnimation {
[self.pathLayer removeAllAnimations];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 3.0;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[self.pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
}
- (void)drawRect:(CGRect)rect {
if (_uipath == NULL)
_uipath = [[UIBezierPath alloc] init];
else
[_uipath removeAllPoints];
[self drawRect:rect :self.graphPoints :self.drawingType ];
}
- (void)refreshRect:(CGRect)rect {
[self setNeedsDisplay];
}
@end
Je sais qu'il y a probablement une raison évidente pour laquelle le chemin d'accès n'est pas d'animer comme il est en cours de dessin (plutôt que d'être montré immédiatement qui est ce qui se passe aujourd'hui), mais j'ai été regarder à la chose depuis si longtemps que je n'ai tout simplement pas le voir.
Aussi, si quelqu'un peut recommander une introduction de base à CAShapeLayers et de l'animation en général, je l'apprécierais. Ne viens pas sur tout qui sont assez bonnes.
merci d'avance.
merci!!!! Check it out
OriginalL'auteur marina | 2013-03-10
Vous devez vous connecter pour publier un commentaire.
Il semble que vous essayez d'animer au sein de
drawRect
(indirectement, au moins). Qui n'a pas tout à fait logique. Vous n'animez pas dansdrawRect
. LedrawRect
est utilisé pour l'élaboration d'une seule image. L'animation est réalisée avec des minuteries ouCADisplayLink
à plusieurs reprises des appelssetNeedsDisplay
(qui sera la cause de iOS pour appeler votredrawRect
) au cours de laquelle vous pouvez dessiner la seule image qui montre la progression de l'animation sur ce point. Mais vous n'avez pasdrawRect
engagement de toute l'animation sur son propre.Mais, puisque vous êtes à l'aide de Core Animation du
CAShapeLayer
etCABasicAnimation
, vous n'avez pas besoin d'un customdrawRect
à tous. Quartz de Base de l'Animation prend juste soin de tout pour vous. Par exemple, voici mon code pour animer le dessin d'unUIBezierPath
:Ensuite, quand je veux démarrer le dessin, l'animation, je viens d'appeler mon
startAnimation
méthode. Je n'ai probablement pas même besoin d'unUIView
sous-classe à tous pour quelque chose d'aussi simple que cela, puisque je ne suis pas en train de changer toutUIView
comportement. Il y a certainement des moments que vous sous-classeUIView
avec une coutumedrawRect
mise en œuvre, mais il n'est pas nécessaire ici.Vous a demandé quelques références:
Mon
View
classe est en fait unUIView
sous-classe, donc je ne comprends pas votre "Vue par opposition àUIView
" question. Mon point principal est que vous n'avez pas besoin de faire personnalisédrawRect
code lors de l'utilisation de Base de l'Animation duCAShapeLayer
. Vous pouvez animer à l'aide,drawRect
avec des minuteries ouCADisplayLink
dansUIView
sous-classe (qui est un peu compliqué), ou l'utilisation de Core Animation. Lorsque j'utiliseCAShapeLayer
, je le fais dansUIViewController
sous-classe (il n'est donc pas la confondre avecdrawRect
alternative), mais c'est une question de préférence personnelle, car il fonctionne dans les deuxUIView
etUIViewController
sous-classes.En bref, il n'y a absolument rien de mal avec le fait de
CAShapeLayer
code dans votreUIView
sous-classe (comme mon illustre l'exemple). Mon point principal est que vous n'avez pas besoin personnalisédrawRect
code lors de l'utilisationCAShapeLayer
.je pense que je commence à comprendre... Comment voulez-vous recommander je désactivez le calque du dessin sous-jacent, quand j'ai besoin de créer un nouveau? Ils ont juste garder le dessin de l'une sur l'autre...
Si vous gardez une référence à l'ancien
CAShapeLayer
, vous pouvez simplement mettre sespath
pour être le nouveau chemin d'accès (et de relancer l'animation, de que vous voulez). Ou vous pouvez prendre le vieuxCAShapeLayer
et appelremoveFromSuperlayer
avant d'ajouter les nouvellesCAShapeLayer
. Les deux techniques fonctionnent très bien, même si le premier est légèrement plus efficace.OriginalL'auteur Rob