0

我正在尝试使用滑块围绕视图中心旋转图像,其中一个用于 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]; 
4

2 回答 2

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

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

于 2013-05-09T05:44:24.327 回答
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];

}

此代码构建了一个集体转换,您可以在每次更改任何滑块时将其应用于视图层。

于 2013-05-10T20:48:05.493 回答