核心動(dòng)畫簡(jiǎn)介:
核心動(dòng)畫直接作用于layer層晶默;在后臺(tái)線程執(zhí)行谨娜,不阻塞主線程
一磺陡、CABasicAnimation (針對(duì)layer的屬性進(jìn)行動(dòng)畫效果)
1、位置動(dòng)畫:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let animation:CABasicAnimation = CABasicAnimation()
animation.keyPath = "position"
animation.duration = 2;
//下面代碼表示動(dòng)畫結(jié)束后坞靶,保持結(jié)束時(shí)的狀態(tài)
animation.fillMode = CAMediaTimingFillMode.forwards
animation.isRemovedOnCompletion = false
animation.toValue = NSValue(cgPoint: CGPoint(x: 300, y: 600))
layer?.add(animation, forKey: nil)
}
其他屬性與上面一樣蝴悉,只要把要做的動(dòng)畫屬性賦值給 animation.duration 即可
二、CAKeyframeAnimation 關(guān)鍵幀動(dòng)畫類
1尿这、屬性介紹:values : 一系列位置信息庆杜; keyTimes : 默認(rèn)是均勻播放的,取值范圍:0-1叨橱;
path : 繪制動(dòng)畫路徑
2断盛、介紹下 淡入淡出動(dòng)畫
class ViewController: UIViewController {
var myView:UIView?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
let myV = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
myV.center = view.center
myV.backgroundColor = UIColor.blue
view.addSubview(myV)
myView = myV;
let animation:CAKeyframeAnimation = CAKeyframeAnimation()
animation.duration = 10
animation.keyPath = "opacity"
let values:[NSNumber] = [NSNumber(value: 0.95),NSNumber(value: 0.90),NSNumber(value: 0.85),NSNumber(value: 0.80),
NSNumber(value: 0.75),NSNumber(value: 0.70),NSNumber(value: 0.65),NSNumber(value: 0.60),NSNumber(value: 0.50),NSNumber(value: 0.40),NSNumber(value: 0.30),NSNumber(value: 0.20)]
animation.values = values
animation.fillMode = CAMediaTimingFillMode.forwards
animation.isRemovedOnCompletion = false
myV.layer.add(animation, forKey: nil)
}
}
其他屬性動(dòng)畫類似,修改values和keypath 即可
3栖博、任意路徑動(dòng)畫
let animation:CAKeyframeAnimation = CAKeyframeAnimation()
animation.duration = 10
let path = CGMutablePath()
path.move(to: CGPoint(x: 40, y: 40))
path.addLine(to: CGPoint(x: 300, y: 300))
path.addLine(to: CGPoint(x: 40, y: 600))
animation.path = path
animation.keyPath = "position";
animation.fillMode = CAMediaTimingFillMode.forwards
animation.isRemovedOnCompletion = false
myV.layer.add(animation, forKey: nil)
4厢洞、 CAAnimationGroup 組合動(dòng)畫介紹
let ca1 = CABasicAnimation(keyPath:"transform.rotation")
ca1.toValue = Double.pi
let scale = CABasicAnimation(keyPath: "transform.scale")
scale.toValue = 0.1
let move = CABasicAnimation(keyPath: "transform.translation")
move.toValue = NSValue(cgPoint: view.center)
let animaGroup = CAAnimationGroup()
animaGroup.animations = [ca1,scale,move]
animaGroup.duration = 6
animaGroup.fillMode = CAMediaTimingFillMode.forwards
animaGroup.isRemovedOnCompletion = false
myV.layer.add(animaGroup, forKey: nil)
三躺翻、綜合案例的實(shí)現(xiàn)
1、水紋按鈕動(dòng)畫效果的實(shí)現(xiàn)
主要分成胰腺癌5個(gè)主要模塊
1)UIBUtton的坐標(biāo)獲取
2)Draw 圓形繪制模塊
3)定時(shí)器刷新
4)其他模塊
5)調(diào)用模塊
代碼如下:代碼主要在自定義button中實(shí)現(xiàn)
import UIKit
class MyButton: UIButton {
var timer:Timer?
var touchPoint:CGPoint?
var viewRadius:CGFloat = 0
var targetAnimationColor:UIColor = UIColor(red: 216.0/255.0, green: 114.0/255.0, blue: 213.0/255.0, alpha: 0.8)
var countNum:Int = 0
override init(frame: CGRect) {
super.init(frame:frame)
backgroundColor = UIColor(red: 50.0/255.0, green: 185.0/255.0, blue: 170.0/255.0, alpha: 1.0)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//此處禁用按鈕點(diǎn)擊事件踊淳,獲取點(diǎn)擊位置,
func starButtonAnimation(send:UIButton,event:UIEvent) {
isUserInteractionEnabled = false;
let button:UIView = send as UIView
let touchSet:NSSet = event.touches(for: button)! as NSSet
var touchArray:[AnyObject] = touchSet.allObjects as [AnyObject]
let touch1:UITouch = touchArray[0] as! UITouch
let point:CGPoint = touch1.location(in: button)
touchPoint = point
timer = Timer.scheduledTimer(timeInterval: 0.2, target: send, selector: #selector(timeaction), userInfo: nil, repeats: true)
RunLoop.main.add(timer!, forMode: RunLoop.Mode.common)
}
//定時(shí)器方法脱茉,定時(shí)刷新上下重新繪制
@objc func timeaction() {
countNum += 1
let dismissTime:DispatchTime = DispatchTime.now() + Double(bitPattern: 0*NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: dismissTime) {
self.viewRadius += 4
self.setNeedsDisplay()
}
if countNum>70 {
countNum = 0
viewRadius = 0
timer?.invalidate()
DispatchQueue.main.asyncAfter(deadline: dismissTime) {
self.viewRadius = 0
self.setNeedsDisplay()
}
self.isUserInteractionEnabled = true
}
}
//繪制圓
override func draw(_ rect: CGRect) {
let ctx:CGContext = UIGraphicsGetCurrentContext()!
let endAngle:CGFloat = CGFloat(Double.pi*2)
ctx.addArc(center: touchPoint ?? center, radius:viewRadius , startAngle: 0, endAngle: endAngle, clockwise: false)
let stockColor:UIColor = targetAnimationColor
stockColor.setStroke()
stockColor.setFill()
ctx.fillPath()
}
}
//以上為自定義按鈕的實(shí)現(xiàn)內(nèi)用琴许,下面我控制器內(nèi)使用的代碼
class ViewController: UIViewController {
var myView:UIView?
var image:UIImageView?
var myBtn:MyButton?
override func viewDidLoad() {
super.viewDidLoad()
let mBtn:MyButton = MyButton(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view.addSubview(mBtn)
mBtn.center = view.center
myBtn = mBtn
mBtn.backgroundColor = UIColor.yellow
mBtn.setTitle("登錄", for: UIControl.State.normal)
mBtn.addTarget(self, action: #selector(buttonClick(_:event:)), for: UIControl.Event.touchUpInside)
}
@objc func buttonClick(_ sender:UIButton,event:UIEvent) {
let bt:MyButton = sender as! MyButton
bt.starButtonAnimation(send: sender, event: event)
}
}
四榜田、CAShapeLayer 主要用于各種圖形繪制(如柱狀圖锻梳、餅狀圖、股票的K線圖等等)
都是基于貝濟(jì)埃曲線繪制辩块,首先來了解什么是貝濟(jì)埃曲線
1荆永、貝濟(jì)埃曲線,它是依據(jù)四個(gè)位置任意點(diǎn)的坐標(biāo)繪制出一條光滑的曲線(如四個(gè)頂點(diǎn)A滔以、B氓拼、C抵碟、D,其中A為繪制起點(diǎn),D為終點(diǎn)拟逮,在A處設(shè)置一條曲線敦迄,保證曲線的切剛好經(jīng)過B,同時(shí)在D出設(shè)置一條曲線罚屋,剛好保證曲線經(jīng)過C點(diǎn))
2、貝濟(jì)埃曲線的使用步驟:
1)創(chuàng)建一個(gè)貝濟(jì)埃曲線對(duì)象(UIBezierPath)
2) 設(shè)置曲線的各種屬性:顏色撕彤、線條粗細(xì)等
3)設(shè)置曲線起始點(diǎn)
4)開始繪制
3猛拴、UIBezierPath 的屬性介紹
1)線條寬度 lineWidth
2) 線條拐角 lineCapStyle (設(shè)置線條首位形狀的)
lineJoinStyle 用于設(shè)置兩條線段銜接處的
func drawLine() {
//設(shè)置路徑
let path = UIBezierPath()
path.move(to: CGPoint(x: 20, y: 40))
path.addLine(to: CGPoint(x: 200, y: 200))
path.addLine(to: CGPoint(x: 40, y: 400))
path.lineCapStyle = CGLineCap.round
path.close()
//開始繪畫
let shapeLayer = CAShapeLayer()
shapeLayer.lineWidth = 10
shapeLayer.lineCap = .round
shapeLayer.lineJoin = .round
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.yellow.cgColor
shapeLayer.path = path.cgPath
view.layer.addSublayer(shapeLayer)
}
4、繪制動(dòng)態(tài)圖表
1)折線圖
import UIKit
class MyChartLine: UIView {
var charLine:CAShapeLayer = CAShapeLayer()
var pathAnimation:CABasicAnimation = CABasicAnimation()
init(frame: CGRect,path:UIBezierPath) {
super.init(frame: frame)
backgroundColor = UIColor.white
clipsToBounds = true
charLine.lineCap = .round
charLine.lineJoin = .round
charLine.fillColor = UIColor.white.cgColor
charLine.strokeColor = UIColor.green.cgColor
charLine.lineWidth = 3
//這個(gè)屬性設(shè)置是為了职员,讓線不是一次性繪畫完成
charLine.strokeEnd = 0.0
charLine.path = path.cgPath
layer.addSublayer(charLine)
pathAnimation.keyPath = "strokeEnd"
pathAnimation.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.linear)
pathAnimation.fromValue = 0.0
pathAnimation.toValue = 1.0
pathAnimation.autoreverses = false
pathAnimation.duration = 5
pathAnimation.fillMode = CAMediaTimingFillMode.forwards
pathAnimation.isRemovedOnCompletion = false
charLine.add(pathAnimation, forKey: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
以上代碼廉邑,是用于折線的view的內(nèi)部代碼,實(shí)現(xiàn)了line和動(dòng)畫糙箍,外界只要傳個(gè)路徑就可以
import UIKit
class MyController1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
let path:UIBezierPath = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 500))
path.addLine(to: CGPoint(x: 40, y: 60))
path.addLine(to: CGPoint(x: 140, y: 300))
path.addLine(to: CGPoint(x: 190, y: 290))
path.addLine(to: CGPoint(x: 240, y: 360))
path.addLine(to: CGPoint(x: 290, y: 180))
path.addLine(to: CGPoint(x: 360, y: 60))
let myLine:MyChartLine = MyChartLine(frame: CGRect(x:0, y: 500, width: UIScreen.main.bounds.size.width, height: 400), path: path)
view.addSubview(myLine)
}
}