【问题标题】:Changing CAShapeLayer's path in for loop makes no effect在 for 循环中更改 CAShapeLayer 的路径无效
【发布时间】:2016-10-13 20:24:12
【问题描述】:

我在for 循环中更改CAShapeLayer 的路径,但它只显示循环的最后结果。我知道,我可以用 CABasicAnimation 做到这一点,但我需要以这种方式改变路径。任何想法如何做到这一点?

UIBezierPath *path = [ShapeManager getCirclePathAppendedWithCirclePathWithRadius:radius
                                                                        andFrame:self.view.bounds];
self.layer.fillRule = kCAFillRuleEvenOdd;
self.layer.fillColor = [UIColor grayColor].CGColor;
self.layer.opacity = 0.5;
self.layer.path = path.CGPath;
[self.view.layer addSublayer:self.layer];
for (int i = 1; i < 100; ++i) {
    path = [ShapeManager getCirclePathAppendedWithCirclePathWithRadius:self.view.bounds.size.width-i
                                                              andFrame:self.view.bounds];
    self.layer.path = path.CGPath;
}

辅助方法

+ (UIBezierPath *)getCirclePathAppendedWithCirclePathWithRadius:(CGFloat)radius andFrame:(CGRect)frame {
    UIBezierPath *backgroundPath = [UIBezierPath bezierPathWithRect:frame];
    [backgroundPath appendPath:[self getCirclePathWithRadius:radius andFrame:frame]];
    return backgroundPath;
}

+ (UIBezierPath *)getCirclePathWithRadius:(CGFloat)radius andFrame:(CGRect)frame {
    CGRect rect = frame;
    UIBezierPath *circlePath;
    circlePath = [UIBezierPath bezierPathWithArcCenter:(CGPoint){rect.size.width/2, rect.size.height/2} radius:radius startAngle:0 endAngle:M_PI*2 clockwise:YES];
    return circlePath;
}

【问题讨论】:

  • 你打算用这个 for 循环实现什么。它不会为任何东西设置动画。如果你设置一个变量百万次,最后你会得到最后一个值,对吧?这里也一样
  • 我正在尝试根据设备位置绘制布局(使用 CoreMotion)。

标签: ios objective-c animation cashapelayer cgpath


【解决方案1】:

使用 CABasicAnimation 是对的。

  1. 删除您的for 循环,它不会完成这项工作。
  2. path 键添加CABasicAnimation,并在其间插入值。这段代码只能在viewDidLoad 方法中调用一次:

UIBezierPath *fromPath = [self.class getCirclePathAppendedWithCirclePathWithRadius:self.view.bounds.size.width andFrame:self.view.bounds];
UIBezierPath *toPath = [self.class getCirclePathAppendedWithCirclePathWithRadius:self.view.bounds.size.width-99 andFrame:self.view.bounds];

CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.fromValue = (id)fromPath.CGPath;
animation.toValue = (id)toPath.CGPath;
animation.duration = 1; 

[layer addAnimation:animation forKey:@"pathAnimation"];
layer.speed = 0;

更新:

  1. 在最后一行中,您将 speed 值设置为 0,因为您要手动设置动画进度:

@property (nonatomic, assign) double progress;

- (void) setProgress: (double) progress {
    _progress = progress;        
    layer.timeOffset = (CFTimeInterval)progress; 
}

这假设动画持续时间为 1.0。否则需要设置

layer.timeOffset = (CFTimeInterval)(progress * totalDuration);

现在只需根据更新的值设置运动回调的进度。

【讨论】:

  • 我试过了。但我需要根据设备位置绘制 ui。我正在以 0.01 时间间隔接收设备运动更新,我需要非常快地制作动画
  • 所以您想在每次调用回调时根据运动值更新路径(每秒约 60 次)?
  • 是的,这就是我需要的
  • @passingnil 你试过timeOffsetlayer.speed = 0 的解决方案吗?
  • @passingnil 最后我们做到了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 2020-01-22
相关资源
最近更新 更多