使用UIBezierPath绘制圆形

15

我正在尝试使用UIBezierPath的addArcWithCenter方法绘制一个圆形:

UIBezierPath *bezierPath = 
  [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0., 0., 100., 100.)];

[bezierPath addArcWithCenter:center 
                      radius:0. 
                  startAngle:0 endAngle:2 * M_PI clockwise:YES];

CAShapeLayer *progressLayer = [[CAShapeLayer alloc] init];

[progressLayer setPath:bezierPath.CGPath];
[progressLayer setStrokeColor:[UIColor colorWithWhite:1. alpha:.2].CGColor];
[progressLayer setFillColor:[UIColor clearColor].CGColor];
[progressLayer setLineWidth:.3 * self.bounds.size.width];
[progressLayer setStrokeStart:_volumeValue/100.];
[progressLayer setStrokeEnd:volume/100.]; // between 0 and 100

[_circleView.layer addSublayer:progressLayer];

但是我得到的是以下内容:

enter image description here

我尝试了不同的参数,但没有运气。

谢谢

更新:

如果我没有解释清楚我正在尝试做什么,我很抱歉:

*背景圆是使用以下方式绘制的:

[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0., 0., 100., 100.)]

我正在尝试使用bezierPathWithOvalInRect逐步绘制红色圆圈,在两个值_volumeValue和volume之间。

但是我无法得到完美的圆形,而是在某个值后得到了水平部分。

输入图像说明


2
哪一位是不工作的位?对我来说它看起来像一个圆圈。你能从图像中去除多余的“噪音”,只显示你感兴趣的东西吗? - Fogmeister
1
另外,volume_volumeValue是什么? - Fogmeister
你正在尝试做什么并不清楚。 - Nikolai Ruhe
好多了,我想我找到它了。已添加答案。 :) - Fogmeister
https://dev59.com/wWQo5IYBdhLWcg3wQdiu#16192736 - pronebird
3个回答

33

好的,试试这个...

UIBezierPath *bezierPath = [UIBezierPath bezierPath];
[bezierPath addArcWithCenter:center radius:50 startAngle:0 endAngle:2 * M_PI clockwise:YES];

CAShapeLayer *progressLayer = [[CAShapeLayer alloc] init];
[progressLayer setPath:bezierPath.CGPath];
[progressLayer setStrokeColor:[UIColor colorWithWhite:1.0 alpha:0.2].CGColor];
[progressLayer setFillColor:[UIColor clearColor].CGColor];
[progressLayer setLineWidth:0.3 * self.bounds.size.width];
[progressLayer setStrokeEnd:volume/100];
[_circleView.layer addSublayer:progressLayer];

volume 应该在0和100之间。

另外,您正在创建一个带有椭圆形的路径,然后添加一条弧线到它上面。请不要这样做。只需将弧形添加到空路径中。

如果要更改弧线起点,则在添加弧线时更改 startAngleendAngle。不要改变描边起始值。

动态更改

[CATransaction begin];
CABasicAnimation *animateStrokeDown = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animateStrokeDown.toValue = [NSNumber numberWithFloat:volume/100.];
[progressLayer addAnimation:animateStrokeDown forKey:@"animateStrokeDown"];
[CATransaction commit];

好的,这将会动画化路径的strokeEnd属性。不过你必须意识到,它是这样工作的...


Begin state: start = 0, end = 6
0123456
-------

// increase volume
Animate to: end = 9
0123456789
----------

// decrease volume
Animate to: end = 1
01
--

起点没有移动,终点移动了。你不是在“填充”线的其余部分,而是改变了这条线。

这就是为什么起点应该始终是0,而只需更改笔画的结束点。


将弧形添加到空路径中有所帮助,但为什么不指定strokeStart和strokeEnd呢?因为我想要在这两个值之间进行动画变化,并从下一次调用中的strokeEnd点开始。 - Mosbah
1
这是动画的代码: [CATransaction begin]; CABasicAnimation *animateStrokeDown = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; animateStrokeDown.fromValue = [NSNumber numberWithFloat:_volumeValue/100.]; animateStrokeDown.toValue = [NSNumber numberWithFloat:volume/100.]; animateStrokeDown.removedOnCompletion = YES; [progressLayer addAnimation:animateStrokeDown forKey:@"animateStrokeDown"]; [CATransaction commit]; - Mosbah
@Mosbah 看一下。你的动画是对的,只是弧线的绘制不正确。 - Fogmeister
对于降低音量,我尝试获取最后添加的图层并将strokeColor设置为clearColor: progressLayer = _circleView.layer.sublayers[_circleView.layer.sublayers.count - 1]; [progressLayer setStrokeColor:[UIColor clearColor].CGColor]; 但我认为这不是最好的方法.. - Mosbah
1
@Mosbah 好的,不需要。你只需要一个图层。它包含了整个圆。你只需要改变那个圆。应该只有一个图层。即一个图层,一个圆,动画化那个圆的端点。 - Fogmeister
显示剩余3条评论

1
startAngle:degreesToRadians(-90) endAngle:0 clockwise:YES

(The reason is that the default coordinate system on iOS has a x-axis pointing to the right, and a y-axis pointing down.)
请阅读此文档 https://developer.apple.com/library/ios/documentation/uikit/reference/UIBezierPath_class/index.html 指定起始角度为0弧度,结束角度为π弧度,并将顺时针参数设置为YES可绘制圆的下半部分。然而,指定相同的起始和结束角度,但将逆时针参数设置为NO则会绘制圆的上半部分。

这不会导致一个圆形。 - Nikolai Ruhe

1
我不知道你的期望以及实际结果的问题所在——但是代码第二行半径为0似乎有些可疑。它只是在当前路径中添加了一个点(该路径已经包括一个圆),位于center处。

你说得完全正确,半径的逻辑值是50。但奇怪的是,即使我改变这个值,我总是得到相同的结果。 - Mosbah

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