首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用CALayer动画化CATransaction?

如何用CALayer动画化CATransaction?
EN

Stack Overflow用户
提问于 2021-10-04 07:49:40
回答 1查看 201关注 0票数 0

我想要动画一个CALAyer,使它看起来像是从任何地方出现。我想我可以首先将图层的转换设置为“缩放为x: 0,y: 0”。然后做一个动画,将转换设置为“缩放为x: 1,y: 1",这是身份。我以为这会使图层看起来从零开始扩大。然而,当我试图实现这一点时,该层立即出现,没有动画。

MCVE:

代码语言:javascript
复制
class MyView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    func commonInit() {
        backgroundColor = .clear
        clipsToBounds = false
        setupLayers()
    }
    
    var squareLayer: CAShapeLayer!
    
    private func setupLayers() {
        layer.sublayers?.forEach { $0.removeFromSuperlayer() }
        squareLayer = CAShapeLayer()
        layer.addSublayer(squareLayer)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        drawLayers()
    }
    
    func drawLayers() {
        squareLayer.fillColor = UIColor.red.cgColor
        squareLayer.path = UIBezierPath(rect: bounds).cgPath
        squareLayer.frame = bounds
    }
}

然后在我的VC里:

代码语言:javascript
复制
@IBAction func click() {
    myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
    view.addSubview(myView)
    myView.drawLayers()
    myView.squareLayer.setAffineTransform(.init(scaleX: 0, y: 0))
    CATransaction.begin()
    CATransaction.setAnimationDuration(1)
    self.myView.squareLayer.setAffineTransform(.init(scaleX: 1, y: 1))
    CATransaction.commit()
}

我认为这是因为第一个setAffineTransform调用也是动画的(我不知道为什么会产生效果,但我怀疑这可能会产生影响),所以我尝试将第二个调用移到完成块中:

代码语言:javascript
复制
@IBAction func click() {
    myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
    view.addSubview(myView)
    myView.drawLayers()
    CATransaction.begin()
    CATransaction.setCompletionBlock {
        CATransaction.begin()
        CATransaction.setAnimationDuration(1)
        self.myView.squareLayer.setAffineTransform(.init(scaleX: 1, y: 1))
        CATransaction.commit()
    }
    myView.squareLayer.setAffineTransform(.init(scaleX: 0, y: 0))
    CATransaction.commit()
}

但是,输出是相同的。另一方面,如果我在第一个setAffineTransform调用之后等待一段时间,那么它可以工作:

代码语言:javascript
复制
@IBAction func click() {
    myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
    view.addSubview(myView)
    myView.drawLayers()
    myView.squareLayer.setAffineTransform(.init(scaleX: 0, y: 0))
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(1)
        self.myView.squareLayer.setAffineTransform(.init(scaleX: 1, y: 1))
        CATransaction.commit()
    }
}

我不认为这是我应该解决这个问题的方式。在此期间,可能会调用一些生命周期方法(我不知道哪个方法),而我应该做的是在该生命周期方法之后执行第二个setAffineTransform调用.(?)

我知道我可以用CABasicAnimation代替,但是我不喜欢使用委托来检测动画的结束。这使得许多事情对我来说非常麻烦。由于延迟0.1秒工作,这不可能是不可能的CATransaction,对吗?

如何使用动画使CALayer出现?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-04 08:04:02

另一方面,

,如果我再等一会儿

是这样的。一个层必须是呈现树的一部分才能被动画化,所以您不能添加一个层并将它作为同一事务的一部分来动画。因此,异步调用等待当前事务提交,下一个事务在附加动画之前启动,实际上是一个完全正确的解决方案。

另一种可能是在添加层之后调用CATransaction.flush();这有效地提前提交了当前事务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69432571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档