我想给一条直线弯曲成一个比较直线的曲线(从“_”到“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帧.