【问题标题】:Why is my image layer rotating around the edge of the image and not the center?为什么我的图像层围绕图像边缘而不是中心旋转?
【发布时间】:2013-05-09 04:55:28
【问题描述】:

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

【问题讨论】:

    标签: ios core-animation calayer catransform3drotate


    【解决方案1】:

    我不确定您的问题的确切答案,因为我无法弄清楚代码中哪里出了问题。默认情况下,事物应该围绕中心旋转。我编写了一个演示应用程序,展示了如何使用 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];
    
    }
    

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

    【讨论】:

    • 这是完美的——正是我想要的!谢谢马特!
    【解决方案2】:

    进行连续变换经常会出错。当您变换 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 系统(尽管它不是!)可能会有所帮助。

    【讨论】:

    • 不幸的是,这并没有什么不同......还有其他建议吗?
    • 实际上,我想知道我是否完全错误地考虑了这一点。我希望我的图像旋转到位,旋转形成的圆的直径应该是图像的宽度。这里发生的是它围绕边缘旋转,使圆的直径成为图像宽度的两倍。我是否需要使用其他类型的动画才能使其原地旋转?
    • 更仔细地查看您的问题(抱歉没有早点这样做!!!)锚点不会影响 3D 变换。动作中心始终是 0,0,0。因此,如果它不围绕您需要旋转的点旋转,则必须进行平移变换以将要旋转的点移动到模型坐标系的中心。所以 - 翻译,然后旋转,然后将其翻译到您想要的位置。这些是让它围绕不同点旋转的步骤。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    相关资源
    最近更新 更多