CAShapeLayer 动画不会停留在屏幕上而是消失
Posted
技术标签:
【中文标题】CAShapeLayer 动画不会停留在屏幕上而是消失【英文标题】:CAShapeLayer animation doesn't stay on screen but disappears 【发布时间】:2015-03-23 12:06:09 【问题描述】:我正在尝试绘制一个动画圆圈,但每个部分都需要有另一种颜色。现在一切正常,除了在我再次调用该方法之前刚刚绘制的我的作品消失了,所以只有最后一部分留下了。我不想要那个,我想要在 4 次之后用不同的颜色笔画绘制一个完整的圆圈。
我怎样才能解决这个问题,它不会消失?
这是我的初始化代码:
- (void)_initCircle
_circle = [CAShapeLayer layer];
_radius = 100;
// 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);
_circle.fillColor = [UIColor clearColor].CGColor;
_circle.lineWidth = 5;
// Add to parent layer
[self.view.layer addSublayer:_circle];
这是我的画作:
- (void)_drawStrokeOnCircleFrom:(float)start to:(float)end withColor:(UIColor *)color
// Configure the apperence of the circle
_circle.strokeColor = color.CGColor;
_circle.strokeStart = start;
_circle.strokeEnd = end;
[CATransaction begin];
// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration = 2.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:start];
drawAnimation.toValue = [NSNumber numberWithFloat:end];
// Experiment with timing to get the appearence to look the way you want
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[CATransaction setCompletionBlock:^
NSLog(@"Complete animation");
_index++;
if(_index < _votes.count)
_startStroke = _endStroke;
_endStroke += [_votes[_index] floatValue] / _totalListens;
[self _drawStrokeOnCircleFrom:_startStroke to:_endStroke withColor:_colors[_index]];
];
// Add the animation to the circle
[_circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
[CATransaction commit];
【问题讨论】:
【参考方案1】:尝试在您的 CABasicAnimation 上设置这些值:
drawAnimation.removedOnCompletion = NO;
drawAnimation.fillMode = kCAFillModeForwards;
【讨论】:
抱歉,我的问题不正确。这两行代码使您的动画在完成后保持持久,这是您需要的。但是你也想要一个五彩的笔触,如果我没看错的话?然后你需要有多个图层,每个图层都有一个不同颜色的笔画段。 这就是问题所在。我需要更多的层次。我已经发布了我的解决方案:) 感谢您的帮助。也添加了填充模式,removedOnCompletion 不再需要了。【参考方案2】:使用“kCAFillModeBoth”对我有用,这两个语句都是必要的:
//to keep it after finished
animation.removedOnCompletion = false;
animation.fillMode = kCAFillModeBoth;
【讨论】:
【参考方案3】:我用这样的额外层解决了这个问题:
- (void)_drawStrokeOnCircle
[self _initCircle];
[CATransaction begin];
for (NSUInteger i = 0; i < 4; i++)
CAShapeLayer* strokePart = [[CAShapeLayer alloc] init];
strokePart.fillColor = [[UIColor clearColor] CGColor];
strokePart.frame = _circle.bounds;
strokePart.path = _circle.path;
strokePart.lineCap = _circle.lineCap;
strokePart.lineWidth = _circle.lineWidth;
// Configure the apperence of the circle
strokePart.strokeColor = ((UIColor *)_colors[i]).CGColor;
strokePart.strokeStart = [_segmentsStart[i] floatValue];
strokePart.strokeEnd = [_segmentsEnd[i] floatValue];
[_circle addSublayer: strokePart];
// Configure animation
CAKeyframeAnimation* drawAnimation = [CAKeyframeAnimation animationWithKeyPath: @"strokeEnd"];
drawAnimation.duration = 4.0;
// Animate from no part of the stroke being drawn to the entire stroke being drawn
NSArray* times = @[ @(0.0),
@(strokePart.strokeStart),
@(strokePart.strokeEnd),
@(1.0) ];
NSArray* values = @[ @(strokePart.strokeStart),
@(strokePart.strokeStart),
@(strokePart.strokeEnd),
@(strokePart.strokeEnd) ];
drawAnimation.keyTimes = times;
drawAnimation.values = values;
drawAnimation.removedOnCompletion = NO;
drawAnimation.fillMode = kCAFillModeForwards;
// Experiment with timing to get the appearence to look the way you want
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[strokePart addAnimation: drawAnimation forKey: @"drawCircleAnimation"];
[CATransaction commit];
- (void)_initCircle
[_circle removeFromSuperlayer];
_circle = [CAShapeLayer layer];
_radius = 100;
// 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);
_circle.fillColor = [UIColor clearColor].CGColor;
_circle.lineWidth = 5;
// Add to parent layer
[self.view.layer addSublayer:_circle];
【讨论】:
【参考方案4】:SWIFT 4、Xcode 11:
let strokeIt = CABasicAnimation(keyPath: "strokeEnd")
let timeLeftShapeLayer = CAShapeLayer()
在你的viewDidLoad
override func viewDidLoad()
super.viewDidLoad()
drawTimeLeftShape()
strokeIt.fillMode = CAMediaTimingFillMode.forwards
strokeIt.isRemovedOnCompletion = false
strokeIt.fromValue = 0
strokeIt.toValue = 1
strokeIt.duration = 2
timeLeftShapeLayer.add(strokeIt, forKey: nil)
并通过UIBezierPath
create 函数绘制圆:
func drawTimeLeftShape()
timeLeftShapeLayer.path = UIBezierPath(
arcCenter: CGPoint(x: myView.frame.midX , y: myView.frame.midY),
radius: myView.frame.width / 2,
startAngle: -90.degreesToRadians,
endAngle: 270.degreesToRadians,
clockwise: true
).cgPath
timeLeftShapeLayer.strokeColor = UIColor.red.cgColor
timeLeftShapeLayer.fillColor = UIColor.clear.cgColor
timeLeftShapeLayer.lineWidth = 1
timeLeftShapeLayer.strokeEnd = 0.0
view.layer.addSublayer(timeLeftShapeLayer)
【讨论】:
以上是关于CAShapeLayer 动画不会停留在屏幕上而是消失的主要内容,如果未能解决你的问题,请参考以下文章