问题
I have an arc that I have drawn using CAShapeLayer and I want it to rotate around the circle's center. I am trying to get this animation using a CABasicAnimation on the 'transform.rotation' property. But the rotation seems is happening about a point that is not the same as the circle's center.
-(void)drawRect:(CGRect)rect{
int radius = 100;
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;
circle.fillColor = [UIColor orangeColor].CGColor;
circle.strokeColor = [UIColor blueColor].CGColor;
circle.lineWidth = 5;
circle.strokeStart = 0.0f;
circle.strokeEnd = 0.1f;
[self.layer addSublayer:circle];
CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
spinAnimation.byValue = [NSNumber numberWithFloat:2.0f*M_PI];
spinAnimation.duration = 4;
spinAnimation.repeatCount = INFINITY;
[circle addAnimation:spinAnimation forKey:@"indeterminateAnimation"];
}
I know its an old problem, but whats the way out. I have tinkered a lot by setting the layer's bounds or the anchor point but it doesn't rotate about the center yet.
circle.bounds = self.frame;
Here is how I add the view to the view controller.
[self.view addSubview:[[ProgressIndicator alloc] initWithFrame:CGRectMake(50, 50, 200, 200)]];
回答1:
This is what I eventually did. The mistake was to add the animation to the sublayer and not the layer. There is no need to tinker with anchorPoint or position here when the rotation is just needed about the center of the circle.
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
int radius = 50;
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blueColor].CGColor;
circle.lineWidth = 5;
circle.strokeStart = 0.0f;
circle.strokeEnd = 0.1f;
[self.layer addSublayer:circle];
}
return self; }
- (void)drawRect:(CGRect)rect {
CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
spinAnimation.byValue = [NSNumber numberWithFloat:2.0f*M_PI];
spinAnimation.duration = 4;
spinAnimation.repeatCount = INFINITY;
[self.layer addAnimation:spinAnimation forKey:@"indeterminateAnimation"]; }
回答2:
Think is better to do something like this)
CGFloat center = CGRectGetWidth(frame) / 2;
CGFloat lineWidth = 5;
CGFloat radius = center - lineWidth / 2;
CGRect bounds = frame;
bounds.origin = CGPointZero;
CAShapeLayer *spinLayer = [CAShapeLayer layer];
spinLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(center, center) radius:radius startAngle:0 endAngle:0.2 clockwise:YES].CGPath;
spinLayer.fillColor = [UIColor clearColor].CGColor;
spinLayer.strokeColor = [UIColor blueColor].CGColor;
spinLayer.lineWidth = 5;
spinLayer.lineCap = kCALineCapRound;
spinLayer.bounds = bounds;
spinLayer.position = CGPointMake(center, center);
[self.layer insertSublayer:spinLayer above:nil];
And animation:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.byValue = [NSNumber numberWithFloat:2.f * M_PI];
animation.duration = 1.5f;
animation.repeatCount = INFINITY;
[spinLayer addAnimation:animation forKey:@"lineRotation"];
[self setNeedsLayout];
Swift 3
var bounds = frame
bounds.origin = CGPoint.zero
let center: CGFloat = frame.size.width
let lineWidth: CGFloat = 5
let radius = center - lineWidth / 2
let spinLayer = CAShapeLayer()
spinLayer.path = UIBezierPath(arcCenter: CGPoint(x: center, y: center),
radius: radius,
startAngle: 0,
endAngle: 0.2,
clockwise: true).cgPath
spinLayer.strokeColor = UIColor.blue.cgColor
spinLayer.fillColor = UIColor.clear.cgColor
spinLayer.lineWidth = lineWidth
spinLayer.lineCap = kCALineCapRound
spinLayer.bounds = bounds
spinLayer.position = CGPoint(x: center, y: center)
view.layer.insertSublayer(spinLayer, above: nil)
let rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation.byValue = NSNumber(value: 2*M_PI as Double)
rotation.duration = 1
rotation.repeatCount = Float.infinity
spinLayer.add(rotation, forKey: "lineRotation")
来源:https://stackoverflow.com/questions/27914358/rotating-a-cashapelayer-arc-about-its-center-using-cabasicanimation