1
votes

I want to simultaneously scale and translate a CALayer from one CGrect (a small one, from a button) to a another (a bigger, centered one, for a view). Basically, the idea is that the user touches a button and from the button, a CALayer reveals and translates and scales up to end up centered on the screen. Then the CALayer (through another button) shrinks back to the position and size of the button.

I'm animating this through CATransform3D matrices. But the CALayer is actually the backing layer for a UIView (because I also need Responder functionality). And while applying my scale or translation transforms separately works fine. The concatenation of both (translation, followed by scaling) offsets the layer's position so that it doesn't align with the button when it shrinks.

My guess is that this is because the CALayer anchor point is in its center by default. The transform applies translation first, moving the 'big' CALayer to align with the button at the upper left corner of their frames. Then, when scaling takes place, since the CALayer anchor point is in the center, all directions scale down towards it. At this point, my layer is the button's size (what I want), but the position is offset (cause all points shrank towards the layer center).

Makes sense?

So I'm trying to figure out whether instead of concatenating translation + scale, I need to:

translate

change anchor point to upper-left.

scale.

Or, if I should be able to come up with some factor or constant to incorporate to the values of the translation matrix, so that it translates to a position offset by what the subsequent scaling will in turn offset, and then the final position would be right.

Any thoughts?

1

1 Answers

7
votes

You should post your code. It is generally much easier for us to help you when we can look at your code.

Anyway, this works for me:

- (IBAction)showZoomView:(id)sender {
    [UIView animateWithDuration:.5 animations:^{
        self.zoomView.layer.transform = CATransform3DIdentity;
    }];
}

- (IBAction)hideZoomView:(id)sender {
    CGPoint buttonCenter = self.hideButton.center;
    CGPoint zoomViewCenter = self.zoomView.center;
    CATransform3D transform = CATransform3DIdentity;
    transform = CATransform3DTranslate(transform, buttonCenter.x - zoomViewCenter.x, buttonCenter.y - zoomViewCenter.y, 0);
    transform = CATransform3DScale(transform, .001, .001, 1);
    [UIView animateWithDuration:.5 animations:^{
        self.zoomView.layer.transform = transform;
    }];
}

In my test case, self.hideButton and self.zoomView have the same superview.