使用 CAAnimation.CurrentMediaTime() 更改显式动画的速度

Posted

技术标签:

【中文标题】使用 CAAnimation.CurrentMediaTime() 更改显式动画的速度【英文标题】:Change Speed of Explicit Animation using CAAnimation.CurrentMediaTime() 【发布时间】:2013-10-23 14:12:38 【问题描述】:

我正在尝试使用 CAAnimation.CurrentMediaTime 更改显式 ios 动画的速度(想想 CABasicAnimation 或 CAKeyFrameAnimation)。这种方法比停止动画,然后以新的持续时间重新启动要好得多。我很接近完成这一切,但我遇到了一个小问题。我有时可以开始、暂停、恢复和更改速度,但更改速度功能有问题。任何人都可以阐明情况吗?我有一些非常简单的代码和下面的示例项目。

类级变量

UIView MyImage;
double timeSincePause = 0;
double pauseTime = 0;

我的暂停功能(有效)

MyImage.Layer.Speed = 0.0f;
MyImage.Layer.TimeOffset = MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer) - timeSincePause;

我的停止功能(有效)

pauseTime = MyImage.Layer.TimeOffset;
MyImage.Layer.Speed = 1.0f;
MyImage.Layer.TimeOffset = 0.0f;
MyImage.Layer.BeginTime = 0.0f;
timeSincePause = (MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer) - pauseTime);
MyImage.Layer.BeginTime = timeSincePause;

我的更改速度功能(不起作用) 要重现问题,只需启动项目并点击更改速度按钮几次。请注意,当它从 100% 速度变为 30% 速度时,它会正确地改变速度,但是当它从 30% 速度变为 100% 速度时,对象的位置会向前跳跃,就好像速度从未改变到 ​​30% 一样。这显然是我正在保存的时间值的问题,我已经尝试过但无法让它工作。

MyImage.Layer.TimeOffset = MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer);
MyImage.Layer.BeginTime = CAAnimation.CurrentMediaTime();
// I have it set so the speed changes back and forth between 100% and 30%.
if ( MyImage.Layer.Speed == 1.0f ) 
    MyImage.Layer.Speed = 0.3f;
else
    MyImage.Layer.Speed = 1.0f;

这里是一个非常简单的示例项目链接,用C# with Xamarin Studio iOS编写:https://www.dropbox.com/s/ndfo12rbemsnp1s/ChangeAnimationSpeed.zip

------ 附加信息 ----------

我已经确定问题是我没有考虑由于速度变化而损失/获得的时间......我只是不确定如何考虑这一点......所以我基本上需要添加另一个名为“totalTimeLostResultingFromSpeedChange”的类级别变量并跟踪它并以某种方式将其考虑在内...

【问题讨论】:

【参考方案1】:

经过几天的努力,我终于解决了这个问题!这是 C# Xamarin iOS project。以下是关键功能。对于不使用游戏引擎在 iOS 中制作动画的任何人来说,这都是一些有价值的东西。

Video

类级变量

    UIView MyImage;

    double currentPauseTime = 0;
    double totalPauseTime = 0;
    double currentChangeSpeedTime = 0;
    double currentTimeLostResultingFromSpeedChange = 0;
    double totalTimeLostResultingFromSpeedChange = 0;

    float currentSpeed = 0;

主要功能

    public void PauseAnimation()
    
        if ( MyImage.Layer.Speed != 0.0f )
        
            Update_TotalTimeLostResultingFromSpeedChange();

            MyImage.Layer.Speed = 0.0f;
            MyImage.Layer.TimeOffset = MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer) - totalPauseTime - totalTimeLostResultingFromSpeedChange;
            currentPauseTime = MyImage.Layer.TimeOffset;
        
    


    public void ResumeAnimation()
    
        if ( MyImage.Layer.Speed == 0.0f )
        
            MyImage.Layer.Speed = 1.0f;
            MyImage.Layer.TimeOffset = 0.0f;
            MyImage.Layer.BeginTime = 0.0f;

            // Because we reset the BeginTime and TimeOffset, Reset the totalTimeLostResultingFromSpeedChange
            Reset_TotalTimeLostResultingFromSpeedChange();

            totalPauseTime = (MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer) - currentPauseTime);
            MyImage.Layer.BeginTime = totalPauseTime;
        


        ChangeAnimationSpeed( currentSpeed );
    


    public void ChangeAnimationSpeed( float speed )
    
        if ( speed != 0.0f )
        
            Update_TotalTimeLostResultingFromSpeedChange();

            currentChangeSpeedTime = MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer);
            MyImage.Layer.TimeOffset = currentChangeSpeedTime - totalPauseTime - totalTimeLostResultingFromSpeedChange;
            MyImage.Layer.BeginTime = CAAnimation.CurrentMediaTime();

            currentSpeed = speed;
            MyImage.Layer.Speed = currentSpeed;
        
    


    public void Update_TotalTimeLostResultingFromSpeedChange()
    
        double value = MyImage.Layer.ConvertTimeFromLayer(CAAnimation.CurrentMediaTime(), MyImage.Layer) - currentChangeSpeedTime;
        currentTimeLostResultingFromSpeedChange = value - (value * MyImage.Layer.Speed);
        totalTimeLostResultingFromSpeedChange += currentTimeLostResultingFromSpeedChange;
    


    public void Reset_TotalTimeLostResultingFromSpeedChange()
    
        totalTimeLostResultingFromSpeedChange = 0;
    

【讨论】:

有效!非常感谢你。我已经尝试修复它好几天了。你的代码给了我很多时间。

以上是关于使用 CAAnimation.CurrentMediaTime() 更改显式动画的速度的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)