iPhone: 画曲线直到成为圆形动画

6
我希望画一条弯曲的线,直到它完成一个完整的旋转并连接成为一个完整的圆,只是圆的轮廓,不填充。这必须在几秒钟内进行动画处理。
有人可以指点我方向吗?我已经问过一个类似的问题similar question,但我表达得不正确,所以每个人都很难理解我的意思,因此它在问题的海洋中丢失了。
非常感谢任何帮助
[编辑]
我目前正在子类化UIView并覆盖drawRect。我找到了绘制填充圆的代码,但我只需要描边。
- (void)drawRect:(CGRect)rect {
// Drawing code

CGRect allRect = self.bounds;
CGRect circleRect = CGRectInset(allRect, 2.0f, 2.0f);

CGContextRef context = UIGraphicsGetCurrentContext();

// Draw background
CGContextSetRGBStrokeColor(context, self.strokeValueRed, self.strokeValueGreen, self.strokeValueBlue, self.strokeValueAlpha); // white
CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 0.1f); // translucent white
CGContextSetLineWidth(context, self.lineWidth);
CGContextFillEllipseInRect(context, circleRect);
CGContextStrokeEllipseInRect(context, circleRect);

// Draw progress
CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2);
CGFloat radius = (allRect.size.width - 4) / 2;
CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees
CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle;
CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); // white
CGContextMoveToPoint(context, center.x, center.y);
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
CGContextClosePath(context);
CGContextFillPath(context);
}

[编辑 #2]

我修改了代码,移除了所有的填充引用,但现在它没有画出任何东西 :( 有什么想法吗?

- (void)drawRect:(CGRect)rect
{
// Drawing code

CGRect allRect = self.bounds;
CGContextRef context = UIGraphicsGetCurrentContext();

// Draw background
CGContextSetRGBStrokeColor(context, self.strokeValueRed, self.strokeValueGreen, self.strokeValueBlue, self.strokeValueAlpha); // white
CGContextSetLineWidth(context, 5);

// Draw progress
CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2);
CGFloat radius = (allRect.size.width - 4) / 2;
CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees
CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle;
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
CGContextStrokePath(context);
}

[编辑 #3] 解决方案

我感觉自己像个傻瓜!问题在于描边颜色值没有被初始化,这意味着线条被绘制出来,但是显然看不到它!

3个回答

16

这与我在你的另一个问题这里所给出的答案相同。

您真正应该做的是使用CAShapeLayer动画化描绘圆形路径的描边。这将利用核心动画进行加速,并且比在 -drawRect:中绘制圆形的部分更加简洁。

下面的代码将创建一个位于屏幕中心的圆形形状图层,并顺时针地动画显示其描边,使其看起来像是正在被绘制。当然,您可以使用任何形状。 (您可以阅读Ole Begemann博客上关于如何动画化形状图层描边的文章以了解更多信息。)

注意:描边属性与图层上的边框属性不同。要更改描边的宽度,应使用“lineWidth”而不是“borderWitdh”等。

// Set up the shape of the circle
int radius = 100;
CAShapeLayer *circle = [CAShapeLayer layer];
// Make a circular shape
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) 
                                         cornerRadius:radius].CGPath;
// Center the shape in self.view
circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius, 
                              CGRectGetMidY(self.view.frame)-radius);

// Configure the apperence of the circle
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blackColor].CGColor;
circle.lineWidth = 5;

// Add to parent layer
[self.view.layer addSublayer:circle];

// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration            = 10.0; // "animate over 10 seconds or so.."
drawAnimation.repeatCount         = 1.0;  // Animate only once..

// Animate from no part of the stroke being drawn to the entire stroke being drawn
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue   = [NSNumber numberWithFloat:1.0f];

// Experiment with timing to get the appearence to look the way you want
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

// Add the animation to the circle
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];

1
嗨David,感谢你的帮助。我将你的解决方案设置为了我的上一个问题的答案。很高兴看到有人理解了我糟糕的问题描述 :) - bennythemink
这里removedOnCompletion应该等于YESstrokeEnd属性默认已经是1.0,一旦完成动画就没有必要将其保留在屏幕上,否则会浪费电池/性能。这是最佳解决方案! - Drmorgan
@Drmorgan 是的,没错。这是一个旧答案,并没有更新以反映最佳实践。它链接到的答案在一段时间前已经更新了,现在这个也更新了。 - David Rönnqvist

3

将所有"Fill"的内容删除。

将末尾的CGContextFillPath改为CGContextStrokePath。

删除末尾附近的CGContextMoveToPoint和CGContextClosePath。它们只是勾勒楔形图案的直线。

可能需要将CGContextMoveToPoint更改为移动到弧线的起始点而不是中心,而不是将其删除。


0
一个非常直观的方法是子类化UIView并让它绘制一个可变长度的弧形。然后,您可以使用定时器定期更新旋转角度。

嘿@Eytan,我已经在做了,但是我就是想不出如何只画出描边而不画实心圆。我已经修改了我的帖子以展示我的代码。 - bennythemink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接