Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS:使用块完成360度旋转,而不是CABASICANIATION_Ios_Core Graphics_Uiviewanimation_Cabasicanimation - Fatal编程技术网

iOS:使用块完成360度旋转,而不是CABASICANIATION

iOS:使用块完成360度旋转,而不是CABASICANIATION,ios,core-graphics,uiviewanimation,cabasicanimation,Ios,Core Graphics,Uiviewanimation,Cabasicanimation,这应该是非常简单的事情,但我并没有成功地使用块来实现这一点。对此有很多问题和答案,但我发现所有问题和答案都是通过使用CABasicAnimation解决的,而不是通过UIView基于块的动画解决的,这正是我所追求的 以下代码无效(基于块),没有动画: CGAffineTransform spin = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(360)); CATransform3D identity = CAT

这应该是非常简单的事情,但我并没有成功地使用块来实现这一点。对此有很多问题和答案,但我发现所有问题和答案都是通过使用
CABasicAnimation
解决的,而不是通过
UIView
基于块的动画解决的,这正是我所追求的

以下代码无效(基于块),没有动画:

CGAffineTransform spin = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(360));

CATransform3D identity = CATransform3DIdentity;
CATransform3D spin2 =  CATransform3DRotate(identity, DEGREES_RADIANS(360), 0.0f, 0.0f, 1.0f);


[UIView animateWithDuration:3.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^
                 {
                     spiningView.transform = spin;
                     //spiningView.layer.transform = spin2;
                     //Have also tried the above, doesn't work either.
                 }
                 completion:^(BOOL finished)
                 {
                     spiningView.transform = spin;
                     //spiningView.layer.transform = spin2;
                 }];
根据我的理解,每次使用基于块时,如果
UIViewAnimation
Block“看到”开始值与最终值相同,则不会出现动画。公平地说,将其设置为360度将意味着对象保持在原来的位置。但它必须是一种使用基于块的动画制作动画的方法,因为以下
CABasicAnimation
将完美地工作:

CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0f];
rotationAnimation.duration = 3.0f;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1;
[spiningView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];  
此外,以下基于块的操作也可以,但动画之间有一个停顿(首先旋转180度,然后再旋转180度以完成旋转),这不是我想要的:

[UIView animateWithDuration:3.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^
                 {
                     spiningView.transform = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(180));;
                 }
                 completion:^(BOOL finished)
                 {                         
                     [UIView animateWithDuration:3.0f
                                           delay:0.0f
                                         options:UIViewAnimationOptionCurveLinear
                                      animations:^
                                      {
                                         spiningView.transform = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(360));
                                      }
                                      completion:^(BOOL finished)
                                      {

                                      }];

                 }];
我知道我可以节省很多时间,只需放弃使用
CABasicAnimation
就可以了,但我想知道在这种情况下,为什么一个有效,而另一个无效(360度旋转)。我希望你能给我一个详细的解释,在这种情况下,在2和一些代码(基于块)之间,可以执行一个完整的360度旋转

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
- (void)rotateSpinningView:(UIView *)spiningView stop:(BOOL)stop {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
    double rads = DEGREES_TO_RADIANS(180);
    if (stop) {
        rads = DEGREES_TO_RADIANS(360);
    }
    [spiningView setTransform:CGAffineTransformMakeRotation(rads)];
} completion:^(BOOL finished) {
    if (finished && !stop && !CGAffineTransformEqualToTransform(spiningView.transform, CGAffineTransformIdentity)) {
        [self rotateSpinningView:spiningView stop:YES];
    }
}];

提前谢谢

使用UIView动画,核心动画计算初始变换和最终变换之间的最短路径。360°旋转不起作用,因为最终变换与初始变换相同

值得一提的是,我刚刚尝试了以下代码,它使四个90°旋转平稳,旋转之间没有延迟:

- (void)rotateSpinningView
{
    [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        [spiningView setTransform:CGAffineTransformRotate(spiningView.transform, M_PI_2)];
    } completion:^(BOOL finished) {
        if (finished && !CGAffineTransformEqualToTransform(spiningView.transform, CGAffineTransformIdentity)) {
            [self rotateSpinningView];
        }
    }];
}

下面是neilco的RotateSpinning视图的更完整版本

它顺时针或逆时针旋转。它有一个
completion:
参数,可以轻松启动和停止

+ (void)rotateSpinningView:(UIView *)view direction:(BOOL)clockwise completion:(void (^)(BOOL finished))completion
{
    int dir = clockwise ? 1 : -1;
    UIViewAnimationOptions opt = UIViewAnimationOptionCurveLinear;
    if (CGAffineTransformEqualToTransform(view.transform, CGAffineTransformIdentity)) {
        opt = UIViewAnimationOptionCurveEaseIn;
    }
    else if (CGAffineTransformEqualToTransform(CGAffineTransformRotate(view.transform, dir * M_PI_2), CGAffineTransformIdentity)) {
        opt = UIViewAnimationOptionCurveEaseOut;
    }
    [UIView animateWithDuration:0.5f delay:0.0f options:opt animations:^{
        [view setTransform:CGAffineTransformRotate(view.transform, dir * M_PI_2)];
    } completion:^(BOOL finished) {
        if (finished && !CGAffineTransformEqualToTransform(view.transform, CGAffineTransformIdentity)) {
            [self rotateSpinningView:view direction:clockwise completion:completion];
        }
        else if (completion && finished && CGAffineTransformEqualToTransform(view.transform, CGAffineTransformIdentity)) {
            completion(finished);
        }
    }];
}

这是iOS 7的关键帧动画非常适合的。例如,您可以将视图的一次完整旋转拆分为三部分:

CGFloat direction = 1.0f;  // -1.0f to rotate other way
view.transform = CGAffineTransformIdentity;
[UIView animateKeyframesWithDuration:1.0 delay:0.0
                               options:UIViewKeyframeAnimationOptionCalculationModePaced | UIViewAnimationOptionCurveEaseInOut
                            animations:^{
                              [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
                                view.transform = CGAffineTransformMakeRotation(M_PI * 2.0f / 3.0f * direction);
                              }];
                              [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
                                view.transform = CGAffineTransformMakeRotation(M_PI * 4.0f / 3.0f * direction);
                              }];
                              [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
                                view.transform = CGAffineTransformIdentity;
                              }];
                            }
                            completion:^(BOOL finished) {}];

请注意,使用UIViewKeyframeAnimationOptionCalculationModelPaced时,可以将所有开始时间和持续时间留空。

@neilco提出了一个非常好的解决方案,但它是一个无限旋转

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
- (void)rotateSpinningView:(UIView *)spiningView stop:(BOOL)stop {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
    double rads = DEGREES_TO_RADIANS(180);
    if (stop) {
        rads = DEGREES_TO_RADIANS(360);
    }
    [spiningView setTransform:CGAffineTransformMakeRotation(rads)];
} completion:^(BOOL finished) {
    if (finished && !stop && !CGAffineTransformEqualToTransform(spiningView.transform, CGAffineTransformIdentity)) {
        [self rotateSpinningView:spiningView stop:YES];
    }
}];
根据他的代码,我修改了一点以实现单循环旋转

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
- (void)rotateSpinningView:(UIView *)spiningView stop:(BOOL)stop {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
    double rads = DEGREES_TO_RADIANS(180);
    if (stop) {
        rads = DEGREES_TO_RADIANS(360);
    }
    [spiningView setTransform:CGAffineTransformMakeRotation(rads)];
} completion:^(BOOL finished) {
    if (finished && !stop && !CGAffineTransformEqualToTransform(spiningView.transform, CGAffineTransformIdentity)) {
        [self rotateSpinningView:spiningView stop:YES];
    }
}];

}

第二个变换(在基于块的解决方案中)不应该使用180度,因为它是在该点(已经是180度)对当前变换特性的变换吗?你也试过在一个
动画
块中使用
cGraffinetTransformMakeRotation(M_PI*2)
吗?@mate在第二个基于块的解决方案中,第二个动画块内实际上是360度的,如果我使用180度,它只会旋转到180度(通过第一个动画块)并停止。我也觉得奇怪,我必须在第二个嵌套块中设置360度,而不是180度。这真的应该是另一个问题,因为有一些好的讨论点可以公开讨论。鉴于这种情况,我将保持我的答案简短,并将其组织为个人评论。基于GCD块的动画是隐式动画,实际上用于为视图的可设置动画的属性设置动画,其中之一是
view.transform
.4。据我所知,双块方法使用不同的转换,因此每个块都会触发关键帧合成,每个块都有自己的
CATransaction
。在第一个块完成之前,第二个块无法计算其关键帧,因此延迟。我怀疑我的递归、单一转换方法正在优化为一个单一的
CATTransaction
。这是一个很酷的解决方案,但为什么四个M_PI_2(90度)旋转而不是两个M_PI(180度)?对我来说,添加
UIViewAnimationOptionCurveLinear
选项是关键。谢谢三个部分是使旋转方向明确无误所需的最少部分(有两个部分,每一步可以顺时针或逆时针旋转)。动画是平滑的。由于ios 7,这应该是答案