Reputation: 2816
I have a CALayer
that I'm explicitly animating to a new position. My toValue
property seems only relative to the layer's initial position.
CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:@"position"];
move.fromValue = [NSValue valueWithCGPoint:CGPointMake(blueDot.position.x, blueDot.position.y)];
move.toValue = [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)];
move.duration = 1.0;
[blueDot addAnimation:move forKey:@"myMoveAnimation"];
blueDot.position = CGPointMake(self.view.center.x, self.view.center.y);
So this code isn't redrawing the layer to the view's center. It seems as if it's really redrawing the layer to CGPointMake(self.view.center.x + blueDot.position.x, self.view.center.y + blueDot.position.y)
, like it's adding the float
values of self.view.center
to the layer's starting position.
Is the toValue
property supposed to act like this? What's the cleanest way to move my blueDot
to the center of the view?
EDIT:
-(void)viewDidLoad {
[super viewDidLoad];
blueDot = [CAShapeLayer layer];
[blueDot setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(self.view.center.x - 60 - 5, 163.5, 10, 10)] CGPath]];
[blueDot setStrokeColor: [UIColor blueColor]CGColor];
[blueDot setFillColor:[UIColor blueColor]CGColor];
[[self.view layer] addSublayer:blueDot];
}
// 163.5 is a placeholder for another view's position value so it's more readable for you guys.
Upvotes: 1
Views: 747
Reputation: 437917
The issue is that you're moving the frame
of the layer, but the blue dot path
of this CAShapeLayer
has been offset within that layer's frame
by self.view.center.x - 60 - 5, 163.5
, the coordinates you specified when creating the path
for that CAShapeLayer
. So when you animate the position
of the layer, the blue dot will still be offset by that amount from this new position
.
The fix is to define the path
of the CAShapeLayer
to be in the upper left corner of the layer, e.g.
CAShapeLayer *blueDot = [CAShapeLayer layer];
blueDot.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(5, 5) radius:5 startAngle:0 endAngle:M_PI * 2 clockwise:true].CGPath; // note that using arc often generates a better looking circle, probably not noticeable at this size, just probably good practice
blueDot.fillColor = [UIColor blueColor].CGColor;
Now when you move the position
, that's where the blue dot's origin will move.
As an aside, I'd generally create a separate UIView
and add this CAShapeLayer
to that. This way, you can enjoy a variety of different features:
UIView
block-based animation; center
to move it around so that when you move its center
to the center
of its superview, it will really be centered (right now, if you move the position
of the layer to self.view.center
, it's not really quite centered, as it will be the upper left corner of the blue dot's layer that will be in the center); UIView
subclass that is IBDesignable
with this dot as a view so that you could add it on a storyboard and see what it looks like; etc.Upvotes: 6
Reputation: 1417
You set the toValue
in the coordinates system of the superview of view
(because of using center
property). Looks like this should work:
CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:@"position"];
move.fromValue = [NSValue valueWithCGPoint:CGPointMake(blueDot.position.x, blueDot.position.y)];
move.toValue = [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds))];
move.duration = 1.0;
[blueDot addAnimation:move forKey:@"myMoveAnimation"];
blueDot.position = CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds));
Upvotes: -1