【问题标题】:How do I achieve continuous rotation of an NSImage inside NSImageView?如何在 NSImageView 中实现 NSImage 的连续旋转?
【发布时间】:2012-06-05 06:41:17
【问题描述】:

未来的观众:

我已经设法完成了这个旋转动画,并且可以在这个问题上找到带有描述的代码。 NSImage rotation in NSView is not working

在继续之前,请投票Duncan C 的答案。当我设法从他的回答中实现这种轮换时。


我有这样的图片,

我想在不同的线程上继续旋转这个同步图标。现在我尝试使用 Quartz composer 并将动画添加到 QCView 中,但效果非常疯狂,而且速度也很慢。

问题:

如何以极少的处理费用连续旋转此图像?

努力

我阅读了 CoreAnimation、Quartz2D 文档,但我没有找到让它工作的方法。到目前为止我唯一知道的是,我必须使用

  • CALayer
  • CAImageRef
  • 仿射变换
  • NSAnimationContext

现在,我并不期待代码,但对伪代码的理解会很棒!

【问题讨论】:

    标签: objective-c macos cocoa core-animation quartz-2d


    【解决方案1】:

    更新:

    我最近了解了另一种处理大于 180 度的旋转或连续旋转的方法。

    有一个称为 CAValueFunction 的特殊对象,可让您使用任意值(包括指定多个完整旋转的值)对图层的变换进行更改。

    您创建图层变换属性的 CABasicAnimation,但随后您提供的值不是提供变换,而是提供新旋转角度的 NSNumber。如果您提供像 20pi 这样的新角度,您的图层将旋转 10 个完整旋转(2pi/旋转)。代码如下所示:

    //Create a CABasicAnimation object to manage our rotation.
    CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform"];
    
    rotation.duration = 10.0;
    CGFLOAT angle = 20*M_PI;
    
    //Set the ending value of the rotation to the new angle.
    rotation.toValue = @(angle);
    
    //Have the rotation use linear timing.
    rotation.timingFunction = 
      [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    
    /*
     This is the magic bit. We add a CAValueFunction that tells the CAAnimation we are 
     modifying the transform's rotation around the Z axis.
     Without this, we would supply a transform as the fromValue and toValue, and 
     for rotations > a half-turn, we could not control the rotation direction.
    
     By using a value function, we can specify arbitrary rotation amounts and 
     directions and even rotations greater than 360 degrees.
    */
    
    rotation.valueFunction = 
      [CAValueFunction functionWithName: kCAValueFunctionRotateZ];
    
    
    
    /*
     Set the layer's transform to it's final state before submitting the animation, so 
     it is in it's final state once the animation completes.
    */
    imageViewToAnimate.layer.transform = 
      CATransform3DRotate(imageViewToAnimate.layer.transform, angle, 0, 0, 1.0);
    
    [imageViewToAnimate.layer addAnimation:rotation forKey:@"transform.rotation.z"];
    

    (我从一个工作示例应用程序中提取了上面的代码,并取出了一些与主题不直接相关的东西。您可以在github上的项目KeyframeViewAnimations(链接)中看到此代码的使用情况。执行旋转的代码在一个名为 `handleRotate' 的方法中

    【讨论】:

    • 围绕 0,0(左下)而不是中心旋转是否有任何问题?这让我发疯了,无论我如何处理锚点和图层位置,我似乎都无法将其围绕中心。
    • @robertmiles3 我相信这与您尝试制作动画的锚点有关。使用 [myView.layer setAnchorPoint:CGPointMake(0.5,,0.5)]
    【解决方案2】:

    让对象旋转超过 180 度实际上有点棘手。问题是您为结束旋转指定了一个变换矩阵,而系统决定向另一个方向旋转。

    我所做的是创建一个小于 180 度的 CABasicAnimation,设置为相加,并具有重复计数。动画中的每一步都会使对象更加生动。

    以下代码取自 iOS 应用程序,但技术在 Mac OS 中是相同的。

      CABasicAnimation* rotate =  [CABasicAnimation animationWithKeyPath: @"transform.rotation.z"];
      rotate.removedOnCompletion = FALSE;
      rotate.fillMode = kCAFillModeForwards;
    
      //Do a series of 5 quarter turns for a total of a 1.25 turns
      //(2PI is a full turn, so pi/2 is a quarter turn)
      [rotate setToValue: [NSNumber numberWithFloat: -M_PI / 2]];
      rotate.repeatCount = 11;
    
      rotate.duration = duration/2;
      rotate.beginTime = start;
      rotate.cumulative = TRUE;
      rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    

    CAAnimation 对象对图层进行操作,因此对于 Mac OS,您需要在界面生成器中设置“wants layer”属性,然后将动画添加到视图的图层。

    为了让您的视图永远旋转,您需要将重复计数设置为一个非常大的数字,例如 1e100。

    创建动画后,您可以使用如下代码将其添加到视图层:

    [myView.layer addAnimation: rotate forKey: @"rotateAnimation"];
    

    这就是它的全部内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      • 2012-07-27
      • 2018-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多