释放双眼,带上耳机,听听看~!
目标
我们要创建一个登录按钮,点击后有3段动画。
每一段动画:动画从UpLoad蓝色长方形条状按钮到刚开始形成圆形
第二段动画:动画从圆弧显示出来开始,顺时针绘制圆弧,直至圆弧最终绘制完成。
第三段动画:从圆弧绘制完成到圆弧伸展为长方形,在伸展过程中,伴随着颜色变化、圆角动画等基础动画效果。
实现过程
1.圆弧绘制类
包含第二段动画实现,通过动画停止代理方法继续下一段动画
import UIKit
protocol CircleDelegate {
func circleAnimationStop()
}
class CircleView: UIView, CAAnimationDelegate {
var lineWidth : NSNumber = 3.0
var strokeColor = UIColor(red: 25/255.0, green: 155/255.0, blue: 200/255.0, alpha: 1.0)
var circle = CAShapeLayer()
var delegate : CircleDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
let startAngle = CGFloat(Float.pi)/2*3
let endAngle = CGFloat(Float.pi)/2*7
let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width/2, y: frame.size.height/2), radius: frame.size.height/2-2, startAngle: startAngle, endAngle: endAngle, clockwise: true)
circle.path = circlePath.cgPath
circle.lineCap = .round
circle.fillColor = UIColor.clear.cgColor
circle.lineWidth = CGFloat(lineWidth.floatValue)
self.layer.addSublayer(circle)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func strokeChart() {
circle.lineWidth = CGFloat(lineWidth.floatValue)
circle.strokeColor = strokeColor.cgColor
let pathAnimation = CABasicAnimation()
pathAnimation.keyPath = "strokeEnd"
pathAnimation.delegate = self
pathAnimation.duration = 3.0
pathAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
pathAnimation.fromValue = 0.0
pathAnimation.toValue = 1.0
circle.add(pathAnimation, forKey: nil)
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
delegate?.circleAnimationStop()
}
}
2.登录按钮类
包含第一段和第三段动画,通过动画停止代理方法来控制3段动画流程
import UIKit
class ButtonView: UIView, CircleDelegate, CAAnimationDelegate {
let FreshBlue = UIColor(red: 25/255.0, green: 155/255.0, blue: 200/255.0, alpha: 1.0)
let FreshGreen = UIColor(red: 150/255.0, green: 203/255.0, blue: 25/255.0, alpha: 1.0)
var view : UIView?
var viewborder : UIView?
var button_x : CGFloat = 0
var button_y : CGFloat = 0
var button_w : CGFloat = 0
var button_h : CGFloat = 0
var label : UILabel?
var circleView : CircleView?
override init(frame: CGRect) {
super.init(frame: frame)
button_x = frame.origin.x
button_y = frame.origin.y
button_w = frame.size.width
button_h = frame.size.height
view = UIView(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
view?.backgroundColor = FreshBlue
self.addSubview(view!)
viewborder = UIView(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
viewborder?.backgroundColor = .clear
viewborder?.layer.borderColor = FreshBlue.cgColor
viewborder?.layer.borderWidth = 3.0
self.addSubview(viewborder!)
circleView = CircleView(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
circleView?.delegate = self
self.addSubview(circleView!)
label = UILabel(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
label?.text = "UpLoad"
label?.textAlignment = .center
label?.textColor = .white
label?.font = UIFont.systemFont(ofSize: 20.0)
self.addSubview(label!)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func startAnimation() {
label?.removeFromSuperview()
let animMakeBigger = CABasicAnimation()
animMakeBigger.keyPath = "cornerRadius"
animMakeBigger.fromValue = 5.0
animMakeBigger.toValue = button_h/2.0
let animBounds = CABasicAnimation()
animBounds.keyPath = "bounds"
animBounds.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: button_h, height: button_h))
let animAlpha = CABasicAnimation()
animAlpha.keyPath = "opacity"
animAlpha.toValue = 0
let animGroup = CAAnimationGroup()
animGroup.duration = 1
animGroup.repeatCount = 1
animGroup.isRemovedOnCompletion = false
animGroup.fillMode = .forwards
animGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
animGroup.animations = [animMakeBigger, animBounds, animAlpha]
let animborder = CABasicAnimation()
animborder.keyPath = "borderColor"
animborder.toValue = UIColor(red: 224/255.0, green: 224/255.0, blue: 224/255.0, alpha: 1.0).cgColor
let animGroupAll = CAAnimationGroup()
animGroupAll.duration = 1
animGroupAll.repeatCount = 1
animGroupAll.isRemovedOnCompletion = false
animGroupAll.fillMode = .forwards
animGroupAll.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
animGroupAll.animations = [animMakeBigger, animBounds, animborder]
animGroupAll.delegate = self
animGroupAll.setValue("allMyAnimationsBoard", forKey: "groupborderkey")
CATransaction.begin()
view?.layer.add(animGroup, forKey: nil)
viewborder?.layer.add(animGroupAll, forKey: nil)
CATransaction.commit()
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if flag {
let animType = anim.value(forKey: "groupborderkey")
let animType1 = anim.value(forKey: "groupborderkey1")
if animType != nil {
if (animType as! NSString).isEqual(to: "allMyAnimationsBoard") {
circleView?.strokeChart()
}
} else if animType1 != nil {
if (animType1 as! NSString).isEqual(to: "allMyAnimationsBoardspread1") {
label = UILabel(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
label?.text = "Complete"
label?.textAlignment = .center
label?.textColor = .white
label?.font = UIFont.systemFont(ofSize: 20)
self.addSubview(label!)
}
}
}
}
func startAnimationSpread() {
let animMakeBigger = CABasicAnimation()
animMakeBigger.keyPath = "cornerRadius"
animMakeBigger.fromValue = button_h/2.0
animMakeBigger.toValue = 0
let animBounds = CABasicAnimation()
animBounds.keyPath = "bounds"
animBounds.fromValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: button_h, height: button_h))
animBounds.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: button_w, height: button_h))
let animAlpha = CABasicAnimation()
animAlpha.keyPath = "opacity"
animAlpha.toValue = 1.0
let animBackground = CABasicAnimation()
animBackground.keyPath = "backgroundColor"
animBackground.toValue = FreshGreen.cgColor
let group = CAAnimationGroup()
group.duration = 1
group.repeatCount = 1
group.isRemovedOnCompletion = false
group.fillMode = .forwards
group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
group.animations = [animMakeBigger, animBounds, animAlpha, animBackground]
let animBorder = CABasicAnimation()
animBorder.keyPath = "borderColor"
animBorder.toValue = FreshGreen.cgColor
let allGroup = CAAnimationGroup()
allGroup.duration = 1
allGroup.repeatCount = 1
allGroup.isRemovedOnCompletion = false
allGroup.fillMode = .forwards
allGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
allGroup.animations = [animMakeBigger, animBounds, animAlpha, animBorder]
allGroup.delegate = self
allGroup.setValue("allMyAnimationsBoardspread1", forKey: "groupborderkey1")
CATransaction.begin()
view?.layer.add(group, forKey: nil)
viewborder?.layer.add(allGroup, forKey: nil)
CATransaction.commit()
}
func circleAnimationStop() {
circleView?.removeFromSuperview()
self.startAnimationSpread()
}
}
3.Loading按钮使用
buttonview = ButtonView(frame: CGRect(x: 100, y: 275, width: 210, height: 70))
singleTap = UITapGestureRecognizer(target: self, action: #selector(viewAction))
buttonview?.addGestureRecognizer(singleTap!)
self.view.addSubview(buttonview!)
@objc func viewAction() {
buttonview?.startAnimation()
}
效果图
