jjzjj

iOS CAKeyFrameAnimation 动画结束时缩放闪烁

coder 2023-09-22 原文

在另一个关键帧动画测试中,我结合了沿着贝塞尔曲线路径移动 UIImageView(称为 theImage)并在移动时将其缩放得更大,从而在结束时将图像放大 2 倍小路。我执行此操作的初始代码包含以下元素以启动动画:

UIImageView* theImage = ....
float scaleFactor = 2.0;
....

theImage.center = destination;
theImage.transform = CGAffineTransformMakeScale(1.0,1.0);

CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(theImage.image.size.height*scaleFactor, theImage.image.size.width*scaleFactor)]];
resizeAnimation.fillMode = kCAFillModeBackwards;
resizeAnimation.removedOnCompletion = NO;  

CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.path = [jdPath path].CGPath;
pathAnimation.fillMode = kCAFillModeBackwards;
pathAnimation.removedOnCompletion = NO;

CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:pathAnimation, resizeAnimation, nil];
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
group.removedOnCompletion = NO;
group.duration = duration;
group.delegate = self;

[theImage.layer addAnimation:group forKey:@"animateImage"];

然后,当动画完成时我想保留较大尺寸的图像,所以我实现:

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
   theImage.transform = CGAffineTransformMakeScale(scaleFactor,scaleFactor);
}

这一切都有效..有点。问题是在动画结束时 theImage 会闪烁一小会儿——足以让它看起来很糟糕。我猜这是动画结束时的过渡,我将转换设置为新的大小。

在试验中,我尝试了一种与上述略有不同的形式,但仍然出现相同的闪烁:

CAKeyframeAnimation *resizeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
NSValue* startSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, 1.0, 1.0, 1.0)];
NSValue* endSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, scaleFactor, scaleFactor, 1.0)]; 
NSArray* sizeKeys = [NSArray arrayWithObjects:startSizeKey, endSizeKey, nil];
[resizeAnimation setValues:sizeKeys];

....

theImage.transform = CGAffineTransformMakeScale(scaleFactor,scaleFactor);

但是当我以与原始尺寸相同的尺寸结束动画时,没有闪烁:

CAKeyframeAnimation *resizeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
NSValue* startSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, 1.0, 1.0, 1.0)];
NSValue* middleSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, scaleFactor, scaleFactor, 1.0)];
NSValue* endSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, 1.0, 1.0, 1.0)]; 
NSArray* sizeKeys = [NSArray arrayWithObjects:startSizeKey, middleSizeKey, endSizeKey, nil];
[resizeAnimation setValues:sizeKeys];

....

theImage.transform = CGAffineTransformMakeScale(1.0,1.0);

所以我的大问题是如何在没有闪烁的情况下为这个图像制作动画,并在动画结束时以不同的尺寸结束?


编辑 3 月 2 日

我最初的测试是放大图像。我只是尝试缩小它 (IE scaleFactor = 0.4) 并且闪烁更加明显,并且就我所看到的而言更加明显。这是事件的顺序:

  1. 原始尺寸的图像绘制在屏幕上的起始位置。
  2. 随着图像沿着路径移动,它会平滑地缩小。
  3. 完全缩小的图像到达路径的尽头。
  4. 然后以原始大小绘制图像。
  5. 图像最终以缩小后的尺寸绘制。

所以我看到的闪烁似乎是第 4 步。


编辑 3 月 22 日

我刚刚向 GitHub 上传了一个演示项目,展示了对象沿贝塞尔曲线路径的移动。代码可以在 PathMove 找到

我也在我的博客 Moving objects along a bezier path in iOS 上写过它

最佳答案

使用 Core Animation 为 View 的层设置动画可能会很棘手。有几件事让它变得困惑:

  • 在图层上设置动画不会更改图层的属性。相反,只要应用了动画,它就会更改“表示层”的属性,该“表示层”会替换屏幕上的原始“模型层”。

  • 更改层的属性通常会向层添加隐式动画,并将属性名称作为动画的键。因此,如果您想显式地为某个属性设置动画,您通常需要将该属性设置为它的最终值,然后添加一个以属性名称为键的动画,以覆盖隐式动画。

  • View 通常会在其图层上禁用隐式动画。它还以其他有些神秘的方式处理其层的属性。

此外,令人困惑的是,您为 View 的边界设置动画以将其放大,但最后切换到缩放转换。

我认为做你想做的最简单的方法是尽可能使用UIView动画方法,并且只为关键帧动画引入Core Animation。在让 UIView 添加自己的动画后,您可以将关键帧动画添加到 View 层,并且您的关键帧动画将覆盖 UIView 添加的动画。

这对我有用:

- (IBAction)animate:(id)sender {
    UIImageView* theImage = self.imageView;
    CGFloat scaleFactor = 2;
    NSTimeInterval duration = 1;

    UIBezierPath *path = [self animationPathFromStartingPoint:theImage.center];
    CGPoint destination = [path currentPoint];

    [UIView animateWithDuration:duration animations:^{
        // UIView will add animations for both of these changes.
        theImage.transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
        theImage.center = destination;

        // Prepare my own keypath animation for the layer position.
        // The layer position is the same as the view center.
        CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        positionAnimation.path = path.CGPath;

        // Copy properties from UIView's animation.
        CAAnimation *autoAnimation = [theImage.layer animationForKey:@"position"];
        positionAnimation.duration = autoAnimation.duration;
        positionAnimation.fillMode = autoAnimation.fillMode;

        // Replace UIView's animation with my animation.
        [theImage.layer addAnimation:positionAnimation forKey:positionAnimation.keyPath];
    }];
}

关于iOS CAKeyFrameAnimation 动画结束时缩放闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9500968/

有关iOS CAKeyFrameAnimation 动画结束时缩放闪烁的更多相关文章

  1. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  2. ruby - 如果满足给定条件,则结束 ruby​​ 程序 - 2

    基本上,我只是试图在满足特定条件时停止程序运行其余行。unlessraw_information.firstputs"Noresultswerereturnedforthatquery"breakend然而,在程序运行之前我得到了这个错误:Invalidbreakcompileerror(SyntaxError)执行此操作的正确方法是什么? 最佳答案 abort("Noresultswerereturnedforthatquery")unlesscondition或unlessconditionabort("Noresultswer

  3. ruby-on-rails - Ruby/Rails 中的夏令时开始和结束日期 - 2

    我正在开发一个Rails应用程序,我需要在其中找到给定特定偏移量或时区的夏令时开始和结束日期。我基本上在我的数据库中保存了从用户浏览器接收到的时区偏移量(“+3”,“-5”),我想在它出现时修改它由于夏令时的变化。我知道Time实例变量有dst?和isdst方法,如果存储在它们中的日期在夏令时与否。>Time.new.isdst=>true但是使用它来查找夏令时的开始和结束日期会占用太多资源,而且我还必须为我拥有的每个时区偏移量执行此操作。我想知道更好的方法。 最佳答案 好的,基于你所说的和@dhouty'sanswer:您希望能够

  4. ruby - 如何在 watir 测试套件结束时关闭浏览器? - 2

    使用ruby​​的watir测试网络应用程序时,浏览器最后会保持打开状态。网上的一些建议是,要进行真正的单元测试,您应该在每次测试时(在拆卸调用中)打开和关闭浏览器,但这很慢而且毫无意义。或者他们做这样的事情:defself.suites=superdefs.afterClass#Closebrowserenddefs.run(*args)superafterClassendsend但这会导致摘要输出不再显示(诸如“100次测试、100次断言、0次失败、0次错误”之类的内容仍应显示)。我怎样才能让ruby​​或watir在我的测试结束时关闭浏览器? 最佳答案

  5. ruby - 从结束值创建一系列字符串 - 2

    我使用irb。下面是我写的代码。“斧头”..“bc”我期待"ax""ay""az""ba"bb""bc"但结果只是“斧头”..“bc”我该如何纠正?谢谢。 最佳答案 >puts("ax".."bc").to_aaxayazbabbbc 关于ruby-从结束值创建一系列字符串,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7617092/

  6. LVGL V8动画 - 2

    动画/*INITIALIZEANANIMATION 初始化一个动画*-----------------------*/lv_anim_ta;lv_anim_init(&a);/*MANDATORYSETTINGS 必选设置*------------------*//*Setthe"animator"function 设置“动画”功能*/lv_anim_set_exec_cb(&a,(lv_anim_exec_xcb_t)lv_obj_set_x);/*Setthe"animator"function*/lv_anim_set_var(&a,obj);/*Lengthoftheanim

  7. ruby - 如何在 vim 中删除 ruby​​ 周围的 block (做/结束) - 2

    如何用vim删除ruby中do/end分隔的环绕block例如(10..20).mapdo|i|(1..10).mapdo|j|pjendend我想做一些类似dsb的事情(删除环绕block)并得到(1..10).mapdo|j|pjend 最佳答案 也许你可以制作nnormap。每个end/do对都在同一个缩进上,所以首先你应该找到对缩进-在这种情况下,下一行相同的缩进(因为你的光标在do行。)所以你可以让vimscript函数找到下一个缩进线并删除它。这是函数的一个例子。您可以自定义您想要的-即)为休息行设置缩进。functio

  8. ruby - 如何检测 Ruby 中方法链的结束 - 2

    我有一个我不久前写的Flickr界面,其中一部分让我很困扰,我想让它变得更好。它的工作方式是我使用缺少的方法从调用flickr对象的方法构造flickr调用的url参数,例如。@flickr.groups.pools.getPhotos(:user_id=>"12656878@N06",:group_id=>"99404851@N00")这些“方法调用”构造了一个如下所示的api调用http://api.flickr.com/services/rest/?method=groups.pools.getPhotos&user_id=1848466274&group_id=99404851

  9. ruby - Carrierwave + MiniMagick - 如何将动画 GIF 压缩到第一帧? - 2

    有人知道如何使用Carrierwave+MiniMagick将动画GIF压缩到第一帧吗? 最佳答案 我认为MiniMagick有一些变化,因为我只花了三个小时试图找出为什么Andrey的代码对我不起作用。我收到以下错误:ActiveRecord::RecordInvalid(Validationfailed:ImageFailedtomanipulatewithMiniMagick,maybeitisnotanimage?OriginalError:Command("mogrify-scene/var/folders/0o/0oqN

  10. ruby-on-rails - Rails Rake Tasks,在期间和结束时输出一条消息 - 2

    我做了一个railsrake任务,可以上传/裁剪/调整(使用回形针)大量图片。我想知道如何在运行时向终端输出消息(例如chipolata.jpg已处理),最后,它需要几分钟才能运行并且有一点反馈会很好。谢谢。 最佳答案 只需使用标准的Rubyputs命令:puts"HellofromRake!"您可以使用字符串插值在循环中输出单个文件名:puts"#{image_filename}processed" 关于ruby-on-rails-RailsRakeTasks,在期间和结束时输出一条消

随机推荐