jjzjj

ios - CALayer 在变换动画后调整回原始大小

coder 2024-01-22 原文

我正在尝试实现两个连续的变换动画。当第一个动画结束时,通过完成处理程序调用第二个动画。因为这是一个转换动画,我的问题是当第一个动画结束时,图层大小调整回原来的大小,然后第二个动画开始。我希望第二个动画在第一个变换动画之后以新的图层大小开始。本帖Objective-C - CABasicAnimation applying changes after animation?说我必须在开始第一个动画之前调整/转换层,这样当第一个动画结束时,层实际上是新的大小。我已经尝试通过更改边界或实际将变换应用于图层来做到这一点,但它仍然无法正常工作。

override func viewDidAppear(_ animated: Bool) {

    buildBar()   

}

func buildBar(){

    progressBar1.bounds = CGRect(x: 0, y: 0, width: 20, height: 5)
    progressBar1.position = CGPoint(x: 0, y: 600)
    progressBar1.backgroundColor = UIColor.white.cgColor
    view.layer.addSublayer(progressBar1)
    extendBar1()

}


func extendBar1(){

     CATransaction.begin()

     let transform1 = CATransform3DMakeScale(10, 1, 1)
     let anim = CABasicAnimation(keyPath: "transform")
     // self.progressBar1.bounds = CGRect(x: 0, y: 0, width: 200, height: 5)
     // self.progressBar1.transform = transform1
     anim.isRemovedOnCompletion = false
     anim.fillMode = kCAFillModeForwards
     anim.toValue = NSValue(caTransform3D:transform1)
     anim.duration = 5.00

     CATransaction.setCompletionBlock {

         self.extendBar2()
     }

     progressBar1.add(anim, forKey: "transform")
     CATransaction.commit()
}

func extendBar2(){

     let transform1 = CATransform3DMakeScale(2, 1, 1)
     let anim = CABasicAnimation(keyPath: "transform")
     anim.isRemovedOnCompletion = false
     anim.fillMode = kCAFillModeForwards
     anim.toValue = NSValue(caTransform3D:transform1)
     anim.duration = 5.00
     progressBar1.add(anim, forKey: "transform")

}

最佳答案

因为您正在修改两个动画中层的变换属性,所以在这里使用 CAKeyframeAnimation 会更容易,它将为您处理动画的链接。

func extendBar(){
     let transform1 = CATransform3DMakeScale(10, 1, 1)
     let transform2 = CATransform3DMakeScale(2, 1, 1)

     let anim = CAKeyframeAnimation()
     anim.keyPath = "transform"
     anim.values = [progressBar1.transform, transform1, transform2] // the stages of the animation
     anim.keyTimes = [0, 0.5, 1] // when they occurs, 0 being the very begining, 1 the end
     anim.duration = 10.00

     progressBar1.add(anim, forKey: "transform")
     progressBar1.transform = transform2 // we set the transform property to the final animation's value
}

关于 valueskeyTimes 的内容的一句话:

  • 我们将第一个值设置为 progressBar1 的当前变换。这将确保我们从当前层的状态开始。
  • keyTimes 中,我们说在开始时,应该使用 values 数组中的第一个值。然后我们说在动画的一半时间,图层应该转换为 values 第二个值。因此,初始状态和第二个状态之间的动画将在此期间发生。然后,在 0.5 到 1 之间,我们将从 tranform1 转到 transform2

您可以在 this very nice article 中阅读有关动画的更多信息来自 objc.io。


如果你真的需要两个不同的动画(因为你可能想在两者之间向 progressBar1 添加 subview ,下面是执行此操作的代码

func extendBar1() {
    CATransaction.begin()
    CATransaction.setCompletionBlock {
        print("side effects")
        extendBar2()
    }
    let transform1 = CATransform3DMakeScale(5, 1, 1)
    let anim = CABasicAnimation(keyPath: "transform")

    anim.fromValue = progressBar1.transform
    anim.toValue = transform1
    anim.duration = 2.00
    progressBar1.add(anim, forKey: "transform")
    CATransaction.setDisableActions(true)
    progressBar1.transform = transform1
    CATransaction.commit()
}

func extendBar2() {
    CATransaction.begin()
    let transform2 = CATransform3DMakeScale(2, 1, 1)
    let anim = CABasicAnimation(keyPath: "transform")

    anim.fromValue = progressBar1.transform
    anim.toValue = transform2
    anim.duration = 2.00
    progressBar1.add(anim, forKey: "transform")
    CATransaction.setDisableActions(true)
    progressBar1.transform = transform2
    CATransaction.commit()
}

这里发生了什么?基本上,我们设置了第一个“正常动画”。所以我们创建动画,它将修改表示层并将实际层设置为最终第一个动画的变换。

然后,当第一个动画完成时,我们调用 extendBar2,它会依次将一个普通动画加入队列。

您还需要在显式更新转换之前调用 CATransaction.setDisableActions(true),否则,核心动画将创建一个隐式动画,它将覆盖之前创建的动画。

关于ios - CALayer 在变换动画后调整回原始大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42521795/

有关ios - CALayer 在变换动画后调整回原始大小的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

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

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

  5. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  6. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  7. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  8. ruby - 改变替换的大小写 - 2

    我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}

  9. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  10. ruby - Sinatra:哈希的未定义方法字节大小 - 2

    很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visitthehelpcenter.关闭9年前。我正在创建一个Sinatra应用程序,它采用上传的CSV文件并将其内容放入哈希中。当我像这样在我的app.rb中引用这个散列时:hash=extract_values(path_to_filename)我不断收到此错误消息:undefinedmethod`bytesize'forHash:0x007fc5e28f2b90#object_idfile:utils.rblocation:bytesiz

随机推荐