IOS:从线到贝塞尔曲线的动画转换

前端之家收集整理的这篇文章主要介绍了IOS:从线到贝塞尔曲线的动画转换前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想给一条直线弯曲成一个比较直线的曲线(从“_”到“n”),是否有图书馆可以帮助我做这件事?

我知道如何用UIBezierPath绘制贝塞尔曲线,我可以快速重绘并逐渐进行转换,但是如果已经做到了,那将会很酷:-)

解决方法

我可以用CADisplayLink做一些事情.例如,您可以使用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.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

我测试了子类UIView以及视图控制器,并且它们每秒产生大约60帧.

猜你在找的iOS相关文章