Search code examples
ioscore-animationcalayercatransform3drotate

Why is my image layer rotating around the edge of the image and not the center?


I'm trying to rotate an image around the center of a view using sliders, one for x, y and Z planes. I would like the image to rotate inside it's framed boundaries (700X700) but for some reason it rotates around the edges of the frame. I tried resetting the anchor point but that doesn't seem to do anything. here's the code to rotate it around the Y axis; you'll notice the anchor point section commented out - it wasn't having any affect at all. Any idea of what i'm doing wrong?

     float angleYDeg = self.ySlider.value;
     float angleYRad = (angleYDeg / 180.0) * M_PI;

    // Disable Animation
     [CATransaction begin];
     [CATransaction setValue:[NSNumber numberWithBool:YES]
                  forKey:kCATransactionDisableActions];

 // Get Layers
     CALayer *containerLayer = [[self.imageView.layer sublayers] objectAtIndex:0];
     CALayer *holder = [containerLayer valueForKey:@"__holderLayer"];

     //CGPoint anchor = holder.anchorPoint;
     //anchor.y = self.imageView.frame.size.height/2;
     //holder.anchorPoint = anchor;

     // Update xAngle Value
     [containerLayer setValue:[NSNumber numberWithFloat:angleYRad] forKey:@"__angleY"];

    // Apply rotations
     CGFloat angleX = [[containerLayer valueForKey:@"__angleX"]floatValue];
     CATransform3D holderTransform = CATransform3DMakeRotation( angleX, 1.0f, 0.0f,  0.0f);
     holderTransform = CATransform3DRotate(holderTransform, angleYRad, 0.0f, 1.0f, 0.0f);
     holder.transform = holderTransform;

     [CATransaction commit];

     // Update Label
     self.yValueLabel.text = [NSString stringWithFormat:@"%4.0fº", angleYDeg]; 

Solution

  • I'm not sure the exact answer to your question as I can't figure out where it's going wrong in the code. By default things should be rotating around the center. I wrote a demo app that shows how to change the rotation for all the axis using a UISlider. I've posted it on github here: https://github.com/perlmunger/AllAxis.git . Here is the gist of the code, though:

    - (IBAction)sliderDidChange:(id)sender
    {
      [self setTransforms];
    }
    
    - (void)setTransforms
    {
      CGFloat x = [_xSlider value];
      CGFloat y = [_ySlider value];
      CGFloat z = [_zSlider value];
    
      CATransform3D transform = CATransform3DIdentity;
      transform.m34 = 1.0f/-800.0f; // perspective
    
      CGFloat rotationValue = x * kRotationMaxInDegrees;
    
      transform = CATransform3DRotate(transform, 
                      degreesToRadians(rotationValue), 1.0f, 0.0f, 0.0f);
    
      rotationValue = y * kRotationMaxInDegrees;
    
      transform = CATransform3DRotate(transform, 
                      degreesToRadians(rotationValue), 0.0f, 1.0f, 0.0f);
    
      rotationValue = z * kRotationMaxInDegrees;
    
      transform = CATransform3DRotate(transform, 
                      degreesToRadians(rotationValue), 0.0f, 0.0f, 1.0f);
    
      [[_rotationView layer] setTransform:transform];
    
    }
    

    This code builds up a collective transform that you apply to the view's layer on each change to any slider.