Posts

Post marked as solved
3 Replies
1.9k Views
I'm creating a crude animation of a changing smile using Core Animation. I'm using CAShapeLayer, CAKeyframeAnimation, and UIBezierPath objects to create the paths that change/animate. The problem I'm seeing is that the original path drawn (i.e. the first keyframe in the set of keyframe values) remains throughout the animation. I was expecting it to only be there for the start of the animation and then animate to the next keyframe value...however, it remains and I would like to get rid of it.Here are some code snippets of my work so far: let width: CGFloat = 240 let height: CGFloat = 120 let shapeLayer = CAShapeLayer() shapeLayer.frame = CGRect(x: 0, y: 0, width: width, height: height) shapeLayer.strokeColor = UIColor.red.cgColor shapeLayer.lineWidth = 2 shapeLayer.fillColor = UIColor.clear.cgColor view1.layer.addSublayer(shapeLayer) let keyframeAnimation = CAKeyframeAnimation(keyPath: "path") keyframeAnimation.values = [ smile(state: .expressionless).cgPath, smile(state: .grin).cgPath, smile(state: .expressionless).cgPath, smile(state: .frown).cgPath, smile(state: .expressionless).cgPath ] keyframeAnimation.duration = 5 keyframeAnimation.calculationMode = .cubic // keeps the animation in its final state and doesn't revert to its original shape keyframeAnimation.isRemovedOnCompletion = false keyframeAnimation.fillMode = CAMediaTimingFillMode.forwards shapeLayer.add(keyframeAnimation, forKey: nil)and the smile code function and related enum:enum SmileState { case grin case frown case expressionless case veryhappy } func smile(state: SmileState) -> UIBezierPath { let curve = UIBezierPath() if (state == .frown) { curve.move(to: CGPoint(x: 0, y: 110)) curve.addQuadCurve(to: CGPoint(x: 240, y: 110), controlPoint: CGPoint(x: 120, y: -290)) } else if (state == .expressionless) { curve.move(to: CGPoint(x: 0, y: 60)) curve.addQuadCurve(to: CGPoint(x: 240, y: 60), controlPoint: CGPoint(x: 120, y: 60)) } else if (state == .grin) { curve.move(to: CGPoint(x: 0, y: 10)) curve.addQuadCurve(to: CGPoint(x: 240, y: 10), controlPoint: CGPoint(x: 120, y: 350)) } curve.close() return curve }Any suggestions on what I could do to remove that "expressionless" path as soon as the animation starts?
Posted
by weslowsk.
Last updated
.
Post marked as solved
1 Replies
1.1k Views
I have a UIImage view that I'm rotating indefinitely vertically by performing a transform on the layer: var keyTransform = CATransform3DIdentity keyTransform.m34 = -0.001 keyFrameAnimation = CAKeyframeAnimation(keyPath: "transform") if let kfAnimation = keyFrameAnimation { kfAnimation.values = [ CATransform3DRotate(keyTransform, 0, 1, 0, 0), CATransform3DRotate(keyTransform, .pi / 2, 1, 0, 0), CATransform3DRotate(keyTransform, .pi, 1, 0, 0), CATransform3DRotate(keyTransform, 3/2 * .pi, 1, 0, 0), CATransform3DRotate(keyTransform, 2 * .pi, 1, 0, 0) ] kfAnimation.beginTime = CACurrentMediaTime() kfAnimation.duration = 8 kfAnimation.repeatCount = .greatestFiniteMagnitude key.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude) key.layer.add(kfAnimation, forKey: "transform") }When a certain event happens (i.e. touch), I want to pause the animation and then fade out (alpha = 0) the layer. let pausedTime = key.layer.convertTime(CACurrentMediaTime(), from: nil) key.layer.speed = 0.0 key.layer.timeOffset = pausedTime UIView.animate(withDuration: self.fadeOutDuration, delay: 0, options: [.curveLinear], animations: { self.key.alpha = 0 }, completion: {(animationsCompleted) in })My problem is that pausing the animation by setting the speed to zero also prevents any further animations (i.e. fading out) from happening.If I remove the transform animation before fading out, then the image no longer pauses at the moment the event happens...rather, the animation resets to the beginning and then fades out...I don't want that behaviour.key.layer.removeAnimation(forKey: "transform")Any suggestions on how I can pause the transform animation and then fade it out?Maybe I can extract a copy of exactly what the layer is rendering at the moment the event occurs, display it in a new sublayer over top of my existing layer, hide the original layer, and then fade out the new layer? I don't know how to implement that idea, though...maybe there's a better way?
Posted
by weslowsk.
Last updated
.
Post not yet marked as solved
5 Replies
1.4k Views
Since bounds is an animatable property of UIView, I wanted to see what happened if I animated the x and y values of a view's bound's origin.My view (view1) has a UILabel inside of it. override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) UIView.animate(withDuration: 2, delay: 0.0, animations: { self.view1.bounds.origin.y = 50 }) }Doing so makes the label animate upwards (50). Similarly, if y is negative, the label will animate downwards. Animating x causes similar behaviour...setting a positive x in the animate block makes the label animate left and negative x makes the label animate right.The documentation and samples I've looked at don't explain enough about animating bounds x/y so I don't understand what's going on.Can someone explain the behaviour I'm seeing?Thanks.
Posted
by weslowsk.
Last updated
.
Post marked as solved
5 Replies
1.7k Views
I have a very simple sample I created to test animating text using UIKIt...I created 3 subviews and put them on the main vieweach subview has a UILabel in itthe labels all have an alpha of 0 specified in their propertiesoutlets for the labels are in my controllercontroller code:override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let duration = TimeInterval(5) UIView.animate(withDuration: duration, delay: 0.0, animations: { self.testText.alpha = 1.0 }) UIView.animate(withDuration: duration, delay: duration, animations: { self.testText2.alpha = 1.0 }) UIView.animate(withDuration: duration, delay: duration * 2, animations: { self.testText3.alpha = 1.0 }) UIView.animate(withDuration: 3, delay: duration * 3, animations: { self.testText.alpha = 0.0 self.testText2.alpha = 0.0 self.testText3.alpha = 0.0 }) }Without the last animate method call, the 3 labels fade in, in sequence.I want to fade them all out at the same time, after the last one has completely faded in.I had expected my last animate method call to do that but, instead, the result is all of labels are displayed as alpha 1 at the beginning of the scene and then after 15 second, they all fade out.Why does adding the last animate method call negate the effects of the first 3 animate method calls?What should I be doing to achieve the effect I want?
Posted
by weslowsk.
Last updated
.