內(nèi)容層動畫(layer層 Core Animation 核心動畫)

核心動畫簡介:
核心動畫直接作用于layer層;在后臺線程執(zhí)行,不阻塞主線程


2FD30689-8D35-4B86-AB3A-5FCBD7BC65C1.png

一、CABasicAnimation (針對layer的屬性進(jìn)行動畫效果)
1、位置動畫:

override func viewWillAppear(_ animated: Bool) {
       super.viewWillAppear(animated)
       let animation:CABasicAnimation = CABasicAnimation()
       animation.keyPath = "position"
       animation.duration = 2;
       //下面代碼表示動畫結(jié)束后,保持結(jié)束時的狀態(tài)
       animation.fillMode = CAMediaTimingFillMode.forwards
       animation.isRemovedOnCompletion = false
       animation.toValue = NSValue(cgPoint: CGPoint(x: 300, y: 600))
       layer?.add(animation, forKey: nil)
   }

其他屬性與上面一樣,只要把要做的動畫屬性賦值給 animation.duration 即可


0B03AE1D-168C-4382-9315-295D6C410158.png

CAB3D1BA-6CD9-41F9-8D7B-5273E9D90CB5.png

二、CAKeyframeAnimation 關(guān)鍵幀動畫類
1、屬性介紹:values : 一系列位置信息; keyTimes : 默認(rèn)是均勻播放的,取值范圍:0-1;
path : 繪制動畫路徑
2、介紹下 淡入淡出動畫

  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)
    }
}

其他屬性動畫類似,修改values和keypath 即可

3、任意路徑動畫

  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 組合動畫介紹

       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、水紋按鈕動畫效果的實(shí)現(xiàn)
主要分成胰腺癌5個主要模塊
1)UIBUtton的坐標(biāo)獲取
2)Draw 圓形繪制模塊
3)定時器刷新
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)
        
        
    }
    //定時器方法,定時刷新上下重新繪制
    @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ù)四個位置任意點(diǎn)的坐標(biāo)繪制出一條光滑的曲線(如四個頂點(diǎn)A、B、C、D,其中A為繪制起點(diǎn),D為終點(diǎn),在A處設(shè)置一條曲線,保證曲線的切剛好經(jīng)過B,同時在D出設(shè)置一條曲線,剛好保證曲線經(jīng)過C點(diǎn))
2、貝濟(jì)埃曲線的使用步驟:
1)創(chuàng)建一個貝濟(jì)埃曲線對象(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、繪制動態(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
       //這個屬性設(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和動畫,外界只要傳個路徑就可以

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)
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容