【问题标题】:Animating a circular UIBezierPath为圆形 UIBezierPath 设置动画
【发布时间】:2013-11-21 21:51:27
【问题描述】:

我有一个项目,我正在根据设定的进度为 UIBezierPath 设置动画。 BezierPath 是圆形的,位于 UIView 中,动画现在使用 CADisplayLink 在 drawRect 中完成。简单地说,基于设定的进度x,路径应该径向扩展(如果x 比以前大)或收缩(如果x 更小)。

self.drawProgress = (self.displayLink.timestamp - self.startTime)/DURATION;

CGFloat startAngle = -(float)M_PI_2;
CGFloat stopAngle = ((self.x * 2*(float)M_PI) + startAngle);
CGFloat currentEndAngle = ((self.oldX * 2*(float)M_PI) + startAngle);
CGFloat endAngle = currentEndAngle-((currentEndAngle-stopAngle)*drawProgress);

UIBezierPath *guideCirclePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];

这是x 自我们上次更新以来缩小的情况。我遇到的问题实际上有几个:

  1. 形状总是从 45º 开始绘制(除非我旋转视图)。我还没有找到任何方法来改变它,将startAngle设置为 -45º 并没有什么区别,因为它总是“弹出”为 45。对此我有什么办法吗,还是我必须求助于其他方法画画?
  2. 还有其他方法可以让这些东西动起来吗?我已经阅读了很多关于使用 CAShapeLayer 的内容,但我还不太了解使用这两种方法的实际区别(就缺点和好处而言)。如果有人能澄清一下,我将非常感激!

更新:我将代码迁移到 CAShapeLayer,但现在我面临一个不同的问题。最好用这张图来描述:

发生的情况是,当层应该收缩时,细外线仍然存在(无论移动方向如何)。当条形缩小时,除非我明确地在其上创建一个新的白色形状,否则 1-x 的增量不会被删除。代码如下。有什么想法吗?

UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:stopAngle clockwise:YES];
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [circlePath CGPath];
circle.strokeStart = 0;
circle.strokeEnd = 1.0*self.progress;

// Colour and other customizations here.

if (self.progress > self.oldProgress) {
    drawAnimation.fromValue = @(1.0*self.oldProgress);
    drawAnimation.toValue = @(circle.strokeEnd);
} else { 
    drawAnimation.fromValue = @(1.0*self.oldProgress);
    drawAnimation.toValue = @(1.0*self.progress);
    circle.strokeEnd = 1.0*self.progress;
}

drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; //kCAMediaTimingFunctionEaseIn
[circle addAnimation:drawAnimation forKey:@"strokeEnd"];

更新 2:我已经解决了大部分其他错误。原来只是我一直很傻,把整个动画过度复杂化(更不用说到处乘以 1,什么?)。我制作了一个我无法解决的错误的 gif 图像:

有什么想法吗?

更新 3:(和关闭)。我设法通过调用摆脱了这个错误

[self.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];

现在一切正常。感谢大家的帮助!

【问题讨论】:

标签: ios objective-c core-animation uibezierpath cadisplaylink


【解决方案1】:

使用 CAShapeLayer 更加容易和清洁。原因是 CAShapeLayer 包含属性 strokeStart 和 strokeEnd。这些值的范围从 0(路径的开始)到 1(路径的结束)并且是可动画的。

通过更改它们,您可以轻松绘制圆的任何弧(或任意路径的任何部分,就此而言)。属性是可动画的,因此您可以创建一个增长/缩小的饼片或部分的动画一个环形。它比在 drawRect 中实现代码更容易、更高效。

【讨论】:

  • 这实际上大大简化了事情,我将代码迁移到使用基于 CAShapeLayer 和 CABasicAnimation 的解决方案,非常感谢!然而,现在我正在经历一个不同的怪事......
  • 这有什么奇怪的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-15
  • 2012-06-07
  • 1970-01-01
  • 2012-11-11
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多