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,这应该是答案