gpt4 book ai didi

ios - 围绕中心制作弧形动画?

转载 作者:行者123 更新时间:2023-11-28 21:59:18 25 4
gpt4 key购买 nike

我正在移植一些看起来有点像这样的动画代码:

- (void)drawRect:(CGRect)rect
{
self.angle += 0.1;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);
CGContextSetLineWidth(context, 2);
CGContextSetLineCap(context, kCGLineCapButt);
CGContextAddArc(context,
self.frame.size.height/2, self.frame.size.height/2, //center
self.frame.size.height/2 - 2, //radius
0.0 + self.angle, M_PI_4 + self.angle, //arc start/finish
NO);
CGContextStrokePath(context);
}

问题在于 drawRect 仅在首次绘制 View 时被调用一次,因此圆弧的位置永远不会更新。

如何才能达到我想要的效果(圆弧缓慢且连续地围绕中心点移动)?我能找到的大多数动画示例都是执行一次性动画(例如淡入),而不是连续的动画。

我还尝试了一些类似的方法:

[arcView animateWithDuration:10.0f
delay:1.0f
options: UIViewAnimationOptionRepeat | UIViewAnimationOptionBeginFromCurrentState
animations: ^(void){
_arcView.transform = CGAffineTransformMakeRotation(self.angle++);
}
completion:NULL];

在显示 View 时,但这似乎也没有做任何事情。

关于我的目标的更多信息:我有一个 View ,我希望能够设置某些状态,例如arcView.state = STATE_READY,并为此更改其动画方式。这是从一个 Android 项目移植过来的,在该项目中,它就像向 View 上的 draw 方法添加逻辑一样简单,并且首选合理类似的东西。

最佳答案

一些观察:

  1. 首先,drawRect 可能不会增加角度。 drawRect 的目的是绘制单个框架,它不应该改变 View 的状态。

  2. 如果您希望 UIView 子类重复更新 angle 并重新绘制自身,您可以设置一个计时器,或者更好的是 CADisplayLink ,它将被定期调用,更新 angle 然后调用 [self setNeedsDisplay] 来更新 View :

    #import "MyView.h"

    @interface MyView ()

    @property (nonatomic, strong) CADisplayLink *displayLink;
    @property (nonatomic) CFTimeInterval startTime;

    @property (nonatomic) CGFloat revolutionsPerSecond;
    @property (nonatomic) CGFloat angle;

    @end

    @implementation MyView

    - (instancetype)initWithCoder:(NSCoder *)coder
    {
    self = [super initWithCoder:coder];
    if (self) {
    self.angle = 0.0;
    self.revolutionsPerSecond = 0.25; // i.e. go around once per every 4 seconds
    [self startDisplayLink];
    }
    return self;
    }

    - (void)startDisplayLink
    {
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    self.startTime = CACurrentMediaTime();
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }

    - (void)stopDisplayLink
    {
    [self.displayLink invalidate];
    self.displayLink = nil;
    }

    - (void)handleDisplayLink:(CADisplayLink *)displayLink
    {
    CFTimeInterval elapsed = CACurrentMediaTime() - self.startTime;

    double revolutions;
    double percent = modf(elapsed * self.revolutionsPerSecond, &revolutions);
    self.angle = M_PI * 2.0 * percent;
    [self setNeedsDisplay];
    }

    - (void)drawRect:(CGRect)rect
    {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);
    CGContextSetLineWidth(context, 2);
    CGContextSetLineCap(context, kCGLineCapButt);
    CGContextAddArc(context,
    self.frame.size.width/2, self.frame.size.height/2, //center
    MIN(self.frame.size.width, self.frame.size.height) / 2.0 - 2.0, //radius
    0.0 + self.angle, M_PI_4 + self.angle, //arc start/finish
    NO);
    CGContextStrokePath(context);
    }

    @end
  3. 一种更简单的方法是更新 View 的 transform 属性,以旋转它。在 iOS 7 及更高版本中,您可以添加带有圆弧的 View ,然后使用类似以下内容旋转它:

    [UIView animateKeyframesWithDuration:4.0 delay:0.0 options:UIViewKeyframeAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
    [UIView addKeyframeWithRelativeStartTime:0.00 relativeDuration:0.25 animations:^{
    self.view.transform = CGAffineTransformMakeRotation(M_PI_2);
    }];
    [UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.25 animations:^{
    self.view.transform = CGAffineTransformMakeRotation(M_PI);
    }];
    [UIView addKeyframeWithRelativeStartTime:0.50 relativeDuration:0.25 animations:^{
    self.view.transform = CGAffineTransformMakeRotation(M_PI_2 * 3.0);
    }];
    [UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
    self.view.transform = CGAffineTransformMakeRotation(M_PI * 2.0);
    }];
    } completion:nil];

    请注意,我将动画分为四个步骤,因为如果您从 0 旋转到 M_PI * 2.0,它不会动画,因为它知道终点与起点相同。因此,通过将它分成四个步骤,它会连续执行四个动画中的每一个。如果在早期版本的 iOS 中执行操作,您可以使用 animateWithDuration 执行类似的操作,但要重复执行,您需要完成 block 来调用另一个旋转。类似于:https://stackoverflow.com/a/19408039/1271826

  4. 最后,如果您想要动画,例如,只是弧的末端(即动画弧的绘制),您可以使用 CABasicAnimation CAShapeLayer:

    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0) radius:MIN(self.view.bounds.size.width, self.view.bounds.size.height) / 2.0 - 2.0 startAngle:0 endAngle:M_PI_4 / 2.0 clockwise:YES];

    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.frame = self.view.bounds;
    layer.path = path.CGPath;
    layer.lineWidth = 2.0;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;

    [self.view.layer addSublayer:layer];

    CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animateStrokeEnd.duration = 10.0;
    animateStrokeEnd.fromValue = @0.0;
    animateStrokeEnd.toValue = @1.0;
    animateStrokeEnd.repeatCount = HUGE_VALF;
    [layer addAnimation:animateStrokeEnd forKey:@"strokeEndAnimation"];

    我知道这可能不是您要找的东西,但我提到它只是为了让您可以将它添加到您的动画“工具带”中。

关于ios - 围绕中心制作弧形动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25507789/

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