IOS:animation从一条线到贝塞尔曲线的变换

我想创build一条弯曲成贝塞尔曲线(从“_”到“n”)的直线,有没有一个库可以帮助我做到这一点?

我知道如何用UIBezierPath绘制一条贝塞尔曲线,我可以快速重绘,并逐步进行转换,但是如果已经有这样的事情,那就太酷了:-)

我可能会用CADisplayLink做些事情。 例如,你可以在你的视图控制器中使用CAShapeLayer来做到这CAShapeLayer ,例如:

 #import "ViewController.h" #import <QuartzCore/QuartzCore.h> @interface ViewController () @property (nonatomic) CFTimeInterval firstTimestamp; @property (nonatomic, strong) CAShapeLayer *shapeLayer; @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic) NSUInteger loopCount; @end static CGFloat const kSeconds = 5.0; @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self addShapeLayer]; [self startDisplayLink]; } - (void)addShapeLayer { self.shapeLayer = [CAShapeLayer layer]; self.shapeLayer.path = [[self pathAtInterval:0.0] CGPath]; self.shapeLayer.fillColor = [[UIColor clearColor] CGColor]; self.shapeLayer.lineWidth = 3.0; self.shapeLayer.strokeColor = [[UIColor redColor] CGColor]; [self.view.layer addSublayer:self.shapeLayer]; } - (void)startDisplayLink { self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)]; [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)stopDisplayLink { [self.displayLink invalidate]; self.displayLink = nil; } - (void)handleDisplayLink:(CADisplayLink *)displayLink { if (!self.firstTimestamp) self.firstTimestamp = displayLink.timestamp; self.loopCount++; NSTimeInterval elapsed = (displayLink.timestamp - self.firstTimestamp); self.shapeLayer.path = [[self pathAtInterval:elapsed] CGPath]; if (elapsed >= kSeconds) { [self stopDisplayLink]; self.shapeLayer.path = [[self pathAtInterval:0] CGPath]; self.statusLabel.text = [NSString stringWithFormat:@"loopCount = %.1f frames/sec", self.loopCount / kSeconds]; } } - (UIBezierPath *)pathAtInterval:(NSTimeInterval) interval { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(0, self.view.bounds.size.height / 2.0)]; CGFloat fractionOfSecond = interval - floor(interval); CGFloat yOffset = self.view.bounds.size.height * sin(fractionOfSecond * M_PI * 2.0); [path addCurveToPoint:CGPointMake(self.view.bounds.size.width, self.view.bounds.size.height / 2.0) controlPoint1:CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0 - yOffset) controlPoint2:CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0 + yOffset)]; return path; } @end 

动画图像


另外,如果你想通过UIView来完成,你可以这样做:

 #import "View.h" #import <QuartzCore/QuartzCore.h> @interface View () @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic) CFTimeInterval firstTimestamp; @property (nonatomic) CFTimeInterval displayLinkTimestamp; @property (nonatomic) NSUInteger loopCount; @end static CGFloat const kSeconds = 5.25; @implementation View - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self startDisplayLink]; } return self; } - (void)startDisplayLink { _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)]; [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)stopDisplayLink { [self.displayLink invalidate]; self.displayLink = nil; } - (void)handleDisplayLink:(CADisplayLink *)displayLink { if (!self.firstTimestamp) self.firstTimestamp = displayLink.timestamp; self.displayLinkTimestamp = displayLink.timestamp; self.loopCount++; [self setNeedsDisplayInRect:self.bounds]; NSTimeInterval elapsed = (displayLink.timestamp - self.firstTimestamp); if (elapsed >= kSeconds) { [self stopDisplayLink]; self.displayLinkTimestamp = self.firstTimestamp + kSeconds; [self setNeedsDisplayInRect:self.bounds]; self.statusLabel.text = [NSString stringWithFormat:@"loopCount = %.1f frames/sec", self.loopCount / kSeconds]; } } - (UIBezierPath *)pathAtInterval:(NSTimeInterval) interval { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(0, self.bounds.size.height / 2.0)]; CGFloat fractionOfSecond = interval - floor(interval); CGFloat yOffset = self.bounds.size.height * sin(fractionOfSecond * M_PI * 2.0); [path addCurveToPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height / 2.0) controlPoint1:CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0 - yOffset) controlPoint2:CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0 + yOffset)]; return path; } - (void)drawRect:(CGRect)rect { NSTimeInterval elapsed = (self.displayLinkTimestamp - self.firstTimestamp); UIBezierPath *path = [self pathAtInterval:elapsed]; [[UIColor redColor] setStroke]; path.lineWidth = 3.0; [path stroke]; } @end 

我testing了子类UIView以及视图控制器,他们都导致大约每秒60帧。