为什么我的图像层围绕图像边缘而不是中心旋转?

时间:2013-05-09 04:55:29

标签: ios core-animation calayer catransform3drotate

我正在尝试使用滑块围绕视图中心旋转图像,一个用于x,y和Z平面。我希望图像在其框架边界内旋转(700X700),但由于某种原因,它会围绕框架的边缘旋转。我尝试重置锚点,但似乎没有做任何事情。这是围绕Y轴旋转它的代码;你会注意到锚点部分被注释掉了 - 它根本没有任何影响。我知道我做错了什么?

     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]; 

2 个答案:

答案 0 :(得分:0)

进行连续变换通常会出错。变换angleX时,将根据新坐标系执行AngleY变换。基本上所有的变换都是相对于“模型”或对象完成的。

大多数人通常希望相对于相机系统进行变换,或者我们正在查看视图。您可能会通过颠倒变换的顺序来获得您想要的结果:

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

 [CATransaction commit];

如果您将其视为一个生命系统(尽管它不是!),如果您正在考虑基于相机坐标而不是模型坐标的所有移动,这可能会有所帮助。

答案 1 :(得分:0)

我不确定你问题的确切答案,因为我无法弄清楚代码中哪里出错了。默认情况下,应该围绕中心旋转。我编写了一个演示应用程序,演示如何使用UISlider更改所有轴的旋转。我已经在github上发布了它:https://github.com/perlmunger/AllAxis.git。以下是代码的要点:

- (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];

}

此代码构建一个集合变换,您可以在每次更改任何滑块时应用于视图的图层。