gpt4 book ai didi

iOS : Animate transformation from a line to a bezier curve

转载 作者:技术小花猫 更新时间:2023-10-29 10:20:09 25 4
gpt4 key购买 nike

我想为一条弯曲成贝塞尔曲线(从“_”到“n”)的直线制作动画,是否有某个库可以帮助我做到这一点?

我知道如何使用 UIBezierPath 绘制贝塞尔曲线,我可以快速重绘并逐步进行转换,但如果已经完成了,那就太酷了:-)

最佳答案

我可能会用 CADisplayLink 做一些事情。例如,您可以在 View Controller 中使用 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

animated image


或者,如果您想通过子类化 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

我测试了子类 UIView 和 View Controller ,它们都产生了大约每秒 60 帧。

关于iOS : Animate transformation from a line to a bezier curve,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14571148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com