如何使我的UIBezierPathanimation与CAShapeLayer?

我试图animation一个UIBezierPath,我已经安装了一个CAShapeLayer来尝试去做。 不幸的是,animation不能正常工作,我不确定任何图层是否有任何影响(因为代码在做图层之前做的是相同的事情)。

这里是实际的代码 – 会爱上任何帮助。 Draw2D是embedded在UIViewController中的UIView的一个实现。 所有的绘图都在Draw2D类中进行。 对[_helper createDrawing …]的调用只是用点来填充_uipathvariables。

Draw2D.h定义了以下属性:

#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; 

以下是实际执行情况:

 // // 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 

我知道可能有一个明显的原因,为什么path不是在绘制animation(而不是立即显示这是现在发生的事情),但是我一直在盯着这个东西很长时间,我只是不看见。

此外,如果任何人都可以推荐CAShapeLayers和animation一般基础底漆,我将不胜感激。 还没有提出任何好的。

提前致谢。

它看起来像你试图在drawRect内animation(间接,至less)。 这不太合理。 你不在drawRectanimation。 drawRect用于绘制一个单一的框架。 一些animation是用定时器或CADisplayLink来完成的,它们反复地调用setNeedsDisplay (这将导致iOS调用你的drawRect ),在这个过程中你可以绘制一个显示animation进度的单帧。 但是你根本没有drawRect自己启动任何animation。

但是,由于您正在使用Core Animation的CAShapeLayerCABasicAnimation ,所以您根本不需要自定义drawRect 。 Quartz的核心animation只是照顾你的一切。 例如,这里是我的代码animationUIBezierPath的绘图:

 #import <QuartzCore/QuartzCore.h> @interface View () @property (nonatomic, weak) CAShapeLayer *pathLayer; @end @implementation View /* // I'm not doing anything here, so I can comment this out - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } */ /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ // It doesn't matter what my path is. I could make it anything I wanted. - (UIBezierPath *)samplePath { UIBezierPath *path = [UIBezierPath bezierPath]; // build the path here return path; } - (void)startAnimation { if (self.pathLayer == nil) { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [[self samplePath] CGPath]; shapeLayer.strokeColor = [[UIColor grayColor] CGColor]; shapeLayer.fillColor = nil; shapeLayer.lineWidth = 1.5f; shapeLayer.lineJoin = kCALineJoinBevel; [self.layer addSublayer:shapeLayer]; self.pathLayer = shapeLayer; } CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = 3.0; pathAnimation.fromValue = @(0.0f); pathAnimation.toValue = @(1.0f); [self.pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"]; } @end 

然后,当我想开始绘制animation时,我只是调用我的startAnimation方法。 我可能甚至不需要一个UIView子类的东西这么简单,因为我实际上并没有改变任何UIView行为。 当然,有些时候你用自定义的drawRect实现了UIView子类,但这里不需要。

你问了一些参考:

  • 如果你还没有看到,我可能会首先回顾一下“苹果核心animation编程指南” 。
  • 对于我来说,当我通过Mike Nachbaur的核心animation教程第4部分时 ,它实际上是从零开始重现他的演示。 显然,您也可以查看第1部分到第3部分。