Анимация рисунка линии
Я пытаюсь оживить рисунок линии следующим образом:
.h
CAShapeLayer *rootLayer;
CAShapeLayer *lineLayer;
CGMutablePathRef path;
.m
path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, self.frame.size.width/2-100, 260);
CGPathAddLineToPoint(path, nil, self.frame.size.width/2+100.0, 260);
CGPathCloseSubpath(path);
self.rootLayer = [CALayer layer];
rootLayer.frame = self.bounds;
[self.layer addSublayer:rootLayer];
self.lineLayer = [CAShapeLayer layer];
[lineLayer setPath:path];
[lineLayer setFillColor:[UIColor redColor].CGColor];
[lineLayer setStrokeColor:[UIColor blueColor].CGColor];
[lineLayer setLineWidth:1.5];
[lineLayer setFillRule:kCAFillRuleNonZero];
[rootLayer addSublayer:lineLayer];
[self performSelector:@selector(startTotalLine) withObject:nil afterDelay:1.5];
- (void)startTotalLine
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"animatePath"];
[animation setDuration:3.5];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animation setAutoreverses:NO];
[animation setFromValue:(id)path];
[animation setToValue:(id)path];
[lineLayer addAnimation:animation forKey:@"animatePath"];
}
Линия была проведена до вызова метода startTotalLine
.
Кроме того, метод startTotalLine
не влияет на строку.
Я хочу, чтобы он анимировал рисунок линии справа налево.
3 ответа:
Я думаю, что самый простой способ сделать то, что вы хотите, - это представить некоторый UIView, который имеет высоту 1,5 пикселя и анимировать его ширину. Спроси меня, если я не понимаю.
Я думаю, что ваш код не работает, потому что ваша переменная
path
не является свойством слоя. Прочитайте инструкции:CABasicAnimation обеспечивает базовую анимацию с одним ключевым кадром возможности для свойства слоя.
И вы делаете здесь что-то странное:
[animation setFromValue:(id)path]; [animation setToValue:(id)path];
Править: Я наткнулся на ... статья , и понял, чего ты пытаешься добиться! Теперь я думаю, что причина вашей неудачи в том, что вы можете анимировать путь, который не изменяет количество точек. И теперь я подумал, что вы можете создать линию пути с двумя точками. Сначала они находятся в одном и том же месте, и другой путь-это линия, которую вы хотите закончить. Теперь одушевляйтесь от первого пути ко второму. Я думаю, что это должно сработать, но я не уверен.
Править: Определенно! Тебе нужен код этого парня. git link .
Я бы сделал это с анимированным свойством.
Для достижения этой цели я бы создал пользовательский классCALayer
- назовем егоLineLayer
. Определите СВОЙСТВОstartPoint
и свойствоlength
. Затем я бы настроил свойствоlength
на "анимируемость".Код для этого будет выглядеть примерно следующим образом:
// LineLayer.h @interface LineLayer: CALayer @property (nonatomic, assign) int length; // This was omitted from the SO code snippet. @property (nonatomic, assign) CGPoint startPoint; @end // LineLayer.m @implementation LineLayer @synthesize length = _length; // This was omitted from the SO code snippet. @synthesize startPoint= _startPoint; - (id) initWithLayer:(id)layer { if(self = [super initWithLayer:layer]) { if([layer isKindOfClass:[LineLayer class]]) { // This bit is required for when we CA is interpolating the values. LineLayer *other = (LineLayer*)layer; self.length = other.length; self.startPoint = other.startPoint; // This was omitted. } } return self; } + (BOOL)needsDisplayForKey:(NSString *)key { if ([key isEqualToString:@"length"]) { return YES; } return [super needsDisplayForKey:key]; } - (void) setLength:(int)newLength { if (newLength < 0) { return; // Fail early. } _length = newLength; [self setNeedsDisplay]; } /* This should have been drawInContext:(CGContextRef)context - (void) drawRect:(CGRect) rect */ - (void) drawInContext:(CGContextRef)context { //...Do your regular drawing here. // This was omitted from the SO code snippet. CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextSetLineWidth(context, 2); CGContextMoveToPoint(context, _startPoint.x, _startPoint.y); CGContextAddLineToPoint(context, _startPoint.x + _length, _startPoint.y); CGContextStrokePath(context); } @end
Тогда в вашем контроллере вида вы можете использовать
LineLayer
Вот так:- (void)viewDidLoad { [super viewDidLoad]; LineLayer *lineLayer = [LineLayer new]; // This was omitted from the SO code snippet. lineLayer.frame = CGRectMake(0, 0, 320, 480); [lineLayer setNeedsDisplay]; // --- lineLayer.startPoint = CGPointMake(0, 100); lineLayer.length = 0; [self.view.layer addSublayer:lineLayer]; // Now animate the changes to the length property CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"length"]; anim.duration = 5; // Change should table about 5 mins. anim.fromValue = [NSNumber numberWithInt:0]; anim.toValue = [NSNumber numberWithInt:200]; [lineLayer addAnimation:anim forKey:@"animateLength"]; lineLayer.length = 200; //Do clean up below... }
Счастливое Кодирование :)
Вот мое решение для вашего случая с использованием "UIBezierPath", "CAShapeLayer" и свойства "strokeEnd":
.m file
@synthesize shapeLayer; [self drawLine]; -(void)drawLine { CGFloat X1 = self.frame.size.width/2-100; CGFloat Y1 = 260; CGFloat X2 = self.frame.size.width/2+100.0; CGFloat Y2 = 260; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(X1, Y1)]; [path addLineToPoint:CGPointMake(X2, Y2)]; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [path CGPath]; shapeLayer.strokeColor = [[UIColor blueColor] CGColor]; shapeLayer.lineWidth = 1.5; shapeLayer.fillColor = [[UIColor redColor] CGColor]; shapeLayer.strokeEnd =0; [self.layer addSublayer:shapeLayer]; [self performSelector:@selector(startTotalLine) withObject:nil afterDelay:1.5]; } - (void)startTotalLine { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; animation.duration = 3.5f; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [animation setAutoreverses:NO]; [animation setFromValue:[NSNumber numberWithInt:0]]; [animation setToValue:[NSNumber numberWithInt:1]]; [shapeLayer addAnimation:animation forKey:@"animatePath"]; }
Значение по умолчанию "strokeEnd" равно 1, поэтому в начале сделайте его равным 0 (строка не появится). Кстати, вот полезные примеры: http://jamesonquave.com/blog/fun-with-cashapelayer/