Ios 圆到矩形变换动画
我对iOS非常陌生,我需要制作以下动画: 圆到矩形的变换应该是平滑的,但在上面的动画中它不是很平滑 我所做的是使用以下代码创建一个圆和一个矩形:Ios 圆到矩形变换动画,ios,swift,core-animation,cashapelayer,cabasicanimation,Ios,Swift,Core Animation,Cashapelayer,Cabasicanimation,我对iOS非常陌生,我需要制作以下动画: 圆到矩形的变换应该是平滑的,但在上面的动画中它不是很平滑 我所做的是使用以下代码创建一个圆和一个矩形: 但是我不知道如何制作动画,有人能帮我吗?为了获得平滑的动画效果,你想看看如何制作cornerRadius属性的动画,而不是乱搞贝塞尔路径。 所以动画是这样的: 设置角半径从当前值到零的动画 将宽度设置为屏幕宽度 反向宽度动画 反向角半径动画 那么,让我们从定义一些我们将要使用的属性开始: class ViewController: UIViewCon
但是我不知道如何制作动画,有人能帮我吗?为了获得平滑的动画效果,你想看看如何制作
cornerRadius
属性的动画,而不是乱搞贝塞尔路径。
所以动画是这样的:
class ViewController: UIViewController {
let animLayer = CALayer() // the layer that is going to be animated
let cornerRadiusAnim = CABasicAnimation(keyPath: "cornerRadius") // the corner radius reducing animation
let cornerRadiusUndoAnim = CABasicAnimation(keyPath: "cornerRadius") // the corner radius increasing animation
let widthAnim = CABasicAnimation(keyPath: "bounds.size.width") // the width animation
let animDuration = NSTimeInterval(1.0) // the duration of one 'segment' of the animation
let layerSize = CGFloat(100) // the width & height of the layer (when it's a square)
...
在这里,我们定义了要使用的层、动画、动画“片段”的持续时间以及CALayer
的大小
接下来,让我们在viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
let rect = view.frame
animLayer.backgroundColor = UIColor.blueColor().CGColor // color of the layer, feel free to change
animLayer.frame = CGRect(x: rect.width-layerSize*0.5, y: rect.height-layerSize*0.5, width: layerSize, height: layerSize)
animLayer.cornerRadius = layerSize*0.5;
animLayer.anchorPoint = CGPoint(x: 1, y: 1) // sets so that when the width is changed, it goes to the left
view.layer.addSublayer(animLayer)
// decreases the corner radius
cornerRadiusAnim.duration = animDuration
cornerRadiusAnim.fromValue = animLayer.cornerRadius
cornerRadiusAnim.toValue = 0;
cornerRadiusAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) // timing function to make it look nice
// inverse of the cornerRadiusAnim
cornerRadiusUndoAnim.duration = animDuration
cornerRadiusUndoAnim.fromValue = 0;
cornerRadiusUndoAnim.toValue = animLayer.cornerRadius
cornerRadiusUndoAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) // timing function to make it look nice
// increases the width, and autoreverses on completion
widthAnim.duration = animDuration
widthAnim.fromValue = animLayer.frame.size.width
widthAnim.toValue = rect.size.width
widthAnim.autoreverses = true
widthAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) // timing function to make it look nice
widthAnim.delegate = self // so that we get notified when the width animation finishes
}
这里没有什么太难的,我们只是定义层和动画属性。我还添加了一些计时功能,以使动画看起来漂亮和平滑,而不是线性
接下来,让我们开始我们的动画。我将在touchesbeated
功能中执行此操作,但您可以将其放在任何位置
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
widthAnim.beginTime = CACurrentMediaTime()+animDuration // starts after the corner radius anim has finished
animLayer.addAnimation(widthAnim, forKey: "widthAnim")
animLayer.addAnimation(cornerRadiusAnim, forKey: "cornerRadius")
CATransaction.begin()
CATransaction.setDisableActions(true) // disables implicit animations
animLayer.cornerRadius = 0
CATransaction.commit()
}
同样,我们使用CATransaction
将corneradius
设置回其原始值。就这样
最终结果
完整项目:如果您希望同时进行缩放和角半径减小,可以显著简化 现在,您不再需要将动画“链接”在一起,因此您可以将它们添加到单个
CAAnimationGroup
并同时运行它们
除了添加groupAnim
属性和删除cornerRadiusEndoaim
之外,我们使用的属性将保持几乎相同
class ViewController2: UIViewController {
let animLayer = CALayer() // the layer that is going to be animated
let cornerRadiusAnim = CABasicAnimation(keyPath: "cornerRadius") // the corner radius reducing animation
let widthAnim = CABasicAnimation(keyPath: "bounds.size.width") // the width animation
let groupAnim = CAAnimationGroup() // the combination of the corner and width animation
let animDuration = NSTimeInterval(1.0) // the duration of one 'segment' of the animation
let layerSize = CGFloat(100) // the width & height of the layer (when it's a square)
...
现在,我们可以添加CAAnimationGroup
的设置,添加角半径动画和缩放动画
override func viewDidLoad() {
super.viewDidLoad()
let rect = view.frame
animLayer.backgroundColor = UIColor.blueColor().CGColor // color of the layer, feel free to change
animLayer.frame = CGRect(x: rect.width-layerSize*0.5, y: rect.height-layerSize*0.5, width: layerSize, height: layerSize)
animLayer.cornerRadius = layerSize*0.5;
animLayer.anchorPoint = CGPoint(x: 1, y: 1) // sets so that when the width is changed, it goes to the left
view.layer.addSublayer(animLayer)
// decreases the corner radius
cornerRadiusAnim.duration = animDuration
cornerRadiusAnim.fromValue = animLayer.cornerRadius
cornerRadiusAnim.toValue = 0;
cornerRadiusAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) // timing function to make it look nice
// increases the width
widthAnim.duration = animDuration
widthAnim.fromValue = animLayer.frame.size.width
widthAnim.toValue = rect.size.width
widthAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) // timing function to make it look nice
// adds both animations to a group animation
groupAnim.animations = [cornerRadiusAnim, widthAnim]
groupAnim.duration = animDuration;
groupAnim.autoreverses = true; // auto-reverses the animation once completed
}
最后,我们可以在触摸视图时运行组动画,两个动画将同时运行(完成后自动反转)
覆盖函数触摸开始(触摸:设置,withEvent事件:UIEvent?){
addAnimation(groupAnim,forKey:“anims”)//同时运行两个动画
}
结果
完整项目:您对如何在放大的同时减小转弯半径有何想法?这两种情况都应该发生一次。我添加了另一个答案(因为这个答案已经足够长了!)说明您将如何执行此操作:)嗨,我对您的代码有一个问题:我删除了自动反转,但当动画结束时,我的视图会立即返回到其原始状态。。。有什么想法吗?谢谢
class ViewController2: UIViewController {
let animLayer = CALayer() // the layer that is going to be animated
let cornerRadiusAnim = CABasicAnimation(keyPath: "cornerRadius") // the corner radius reducing animation
let widthAnim = CABasicAnimation(keyPath: "bounds.size.width") // the width animation
let groupAnim = CAAnimationGroup() // the combination of the corner and width animation
let animDuration = NSTimeInterval(1.0) // the duration of one 'segment' of the animation
let layerSize = CGFloat(100) // the width & height of the layer (when it's a square)
...
override func viewDidLoad() {
super.viewDidLoad()
let rect = view.frame
animLayer.backgroundColor = UIColor.blueColor().CGColor // color of the layer, feel free to change
animLayer.frame = CGRect(x: rect.width-layerSize*0.5, y: rect.height-layerSize*0.5, width: layerSize, height: layerSize)
animLayer.cornerRadius = layerSize*0.5;
animLayer.anchorPoint = CGPoint(x: 1, y: 1) // sets so that when the width is changed, it goes to the left
view.layer.addSublayer(animLayer)
// decreases the corner radius
cornerRadiusAnim.duration = animDuration
cornerRadiusAnim.fromValue = animLayer.cornerRadius
cornerRadiusAnim.toValue = 0;
cornerRadiusAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) // timing function to make it look nice
// increases the width
widthAnim.duration = animDuration
widthAnim.fromValue = animLayer.frame.size.width
widthAnim.toValue = rect.size.width
widthAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) // timing function to make it look nice
// adds both animations to a group animation
groupAnim.animations = [cornerRadiusAnim, widthAnim]
groupAnim.duration = animDuration;
groupAnim.autoreverses = true; // auto-reverses the animation once completed
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
animLayer.addAnimation(groupAnim, forKey: "anims") // runs both animations concurrently
}