尝试使用 CALayers 为水龙头的水滴设置动画
Posted
技术标签:
【中文标题】尝试使用 CALayers 为水龙头的水滴设置动画【英文标题】:Trying to animate a drop from a faucet with CALayers 【发布时间】:2018-09-11 19:19:57 【问题描述】:我正在尝试创建一个 UIView 子类,该子类显示一个水龙头,其水滴不断增长然后下降。我对不同部分进行的实验越多,我就越感到困惑。
我创建了两个图形:
我创建了一个 UIView 类:
class ValvebeatView: UIView
var faucet = CALayer()
var drip = CALayer()
func _init()
self.faucet.contents = #imageLiteral(resourceName: "faucet").cgImage
self.drip.contents = #imageLiteral(resourceName: "droplet").cgImage
self.layer.insertSublayer(self.drip, above: nil)
self.layer.insertSublayer(self.faucet, above: self.drip)
override init(frame: CGRect)
super.init(frame: frame)
self._init()
required init(coder aDecoder: NSCoder)
super.init(coder: aDecoder)!
self._init()
override func layoutSubviews()
super.layoutSubviews()
self.faucet.frame = self.bounds
self.drip.frame = self.bounds
func startDrop()
如果我在我的应用程序中添加这个视图,我会得到如下所示的内容:
这恰到好处。但是,当我尝试尝试改变水滴的外观时,没有任何效果。到目前为止我已经尝试/学到了什么:
设置drip.contentScale
似乎没有任何作用。文档听起来好像这只是一个提示?
我玩过contentsRect
,这似乎改变了它,但在阅读文档后,它似乎表明它决定了显示的放置图像的子部分。我想展示所有的下降,我只想从小处着手,让它膨胀,然后切换到向下平移。
各种变换选项(缩放然后平移)似乎是正确的处理方式。但这也不会产生正确的结果。例如,如果我为self.valvebeatView.drip.transform = CATransform3DMakeScale(0.1, 0.1, 1)
设置了轻击手势,它会暂时膨胀 10 倍,然后恢复为原始大小。但更奇怪的是,如果我改为使用self.valvebeatView.drip.transform = CATransform3DMakeScale(10.0, 10.0, 1)
,它会做同样的事情?!?!?为什么它至少没有收缩然后恢复到原来的形状?
我想知道是不是因为我的重力设置为默认值(即调整大小)。但是,当我将其更改为中心时,原来的水滴已经过大了。
我的问题是,我想使用哪些钩子(变换、位置等?)动画我的水滴从小规模增长到正常,然后向下下降。
【问题讨论】:
【参考方案1】:假设您确实希望坚持使用图层和图层动画来执行此操作,而不是使用更简单的视图和视图动画方法。
然后在您列出的相当古怪的想法中,只更改transform
并且可能还更改position
(如果这个想法也是移动下降)是正确的。您需要了解 CABasicAnimation。要以一种很好的协调方式将水滴的增长与水滴的下降结合起来,请使用 CAAnimationGroup。
【讨论】:
但是如果这个想法是创造一个稳定的水滴流,这可能是一个 CAEmitter 的工作。 我对如何使用两个堆叠的图像视图来做到这一点相当有信心。然后只需为变换或什至下降的帧/边界设置动画。我认为图层是做事的“首选”方式。我真正的挫败感是我在应用任何动画类之前很久就更改变换的经验(迄今为止我已经使用了很多,但通常只用于旋转)。 这不会改变我的答案。【参考方案2】: func startDrop()
self.drip.contentsGravity = kCAGravityCenter
let center = CGPoint.init(x: self.frame.width / 2.0, y: self.frame.height / 2.0)
let scaleAnimation = CAKeyframeAnimation.init(keyPath: "contentsScale")
scaleAnimation.values = [3, 1, 1 ]
scaleAnimation.keyTimes = [0,0.2, 1]
scaleAnimation.duration = 3
scaleAnimation.isRemovedOnCompletion = false
scaleAnimation.repeatCount = Float.greatestFiniteMagnitude
let positionAnimation = CAKeyframeAnimation.init(keyPath: "position")
positionAnimation.values = [center , center, CGPoint.init(x:center.x ,y:center.y * 2) ]
positionAnimation.keyTimes = [0,0.2, 1]
positionAnimation.duration = 3
positionAnimation.repeatCount = Float.greatestFiniteMagnitude
positionAnimation.isRemovedOnCompletion = false
self.drip.add(scaleAnimation, forKey: "scale")
self.drip.add(positionAnimation, forKey: "pos")
【讨论】:
以上是关于尝试使用 CALayers 为水龙头的水滴设置动画的主要内容,如果未能解决你的问题,请参考以下文章