I'm having a imageview and I want that imageview to animate with a color. So my image is first a green one and then I want to animate it to a orange one.
This is my code:
class TestView: UIView {
func startAnimate(){
let size:CGSize = self.bounds.size
let layer = UIImageView(image: UIImage(named: "LaunchIcon"))
layer.frame = self.bounds
let initialRect:CGRect = CGRect.init(x: 0, y: size.height, width: size.width, height: 0)
let finalRect:CGRect = CGRect.init(x: 0, y: size.height, width: size.width, height: size.height)
let sublayer = CALayer()
sublayer.frame = initialRect
sublayer.backgroundColor = UIColor.orange.cgColor
sublayer.opacity = 0.5
let mask:CAShapeLayer = CAShapeLayer()
mask.frame = self.bounds
mask.path = UIBezierPath(rect: self.bounds).cgPath
mask.fillColor = UIColor.black.cgColor
layer.layer.addSublayer(sublayer)
layer.layer.mask = mask
self.layer.addSublayer(layer.layer)
let boundsAnim:CABasicAnimation = CABasicAnimation(keyPath: "bounds")
boundsAnim.toValue = NSValue.init(cgRect:finalRect)
let animationGroup = CAAnimationGroup()
animationGroup.animations = [boundsAnim]
animationGroup.isRemovedOnCompletion = false
animationGroup.duration = 2
animationGroup.fillMode = kCAFillModeForwards
sublayer.add(animationGroup, forKey: nil)
}
}
My result:
The first problem is that the orange is taking the whole frame and not just my image. The second problem is that it doesn't fill to the top.
Some of the issues with your code:
You add a rectangular mask
to a layer, which is not affecting rendering at all. You never change it's frame, position, shape or anything else, so it's purpose is unclear.
sublayer
is supposed to be visible inside your glass shape only, right? But in code you define it as a rectengular and it is a subview, so there is no reason it would be trimmed by the shape of your glass image.
Please don't call view
s as layer, it's confusing for anyone who is reading your code. If it's not a layer, don't call it layer, simple as that.
let layer = UIImageView(image: UIImage(named: "LaunchIcon"))
CABasicAnimation
Working solution:
In fact you don't need to use CoreAnimation here, you can implement this with a higher level plain UIKit
. Your best friends in this case are mask property of UIView
and animateWithDuration method:
class GlassView: UIView {
let liquidView = UIView() //is going to be animated from bottom to top
let shapeView = UIImageView() //is going to mask everything with alpha mask
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
self.backgroundColor = UIColor.darkGray
self.liquidView.backgroundColor = UIColor.orange
self.shapeView.contentMode = .scaleAspectFit
self.shapeView.image = UIImage(named: "glass")
self.addSubview(liquidView)
self.mask = shapeView
layoutIfNeeded()
reset()
}
override func layoutSubviews() {
super.layoutSubviews()
liquidView.frame = self.bounds
shapeView.frame = self.bounds
}
func reset() {
liquidView.frame.origin.y = bounds.height
}
func animate() {
reset()
UIView.animate(withDuration: 1) {
self.liquidView.frame.origin.y = 0
}
}
}
Output:
used mask
Implementation details:
The view’s alpha channel determines how much of the view’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through but fully transparent pixels block that content.
Make sure your mask image is .png
and contains a shape on a transparent background.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With