17

我有一个项目,我正在根据设定的进度为 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,但现在我面临一个不同的问题。最好用这张图片来描述:

在此处输入图像描述

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

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)];

现在一切正常。感谢所有的帮助!

4

1 回答 1

11

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

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

于 2013-11-21T21:56:37.487 回答