Swift 波浪動畫

Brocadecarp發表於2018-04-23

Untitled.gif

class WaveView: UIView {

    var firstWaveColor = UIColor() // 第一個波浪顏色
    var secondWaveColor = UIColor() // 第二個波浪顏色
    
    var waveDisplaylink : CADisplayLink!
    var firstWaveLayer : CAShapeLayer! // 第一個波浪
    var secondWaveLayer : CAShapeLayer! // 第二個波浪
    
    var waveAmplitude : CGFloat = 0.0 // 波紋振幅
    var waveCycle : CGFloat = 0.0 // 波紋週期
    var waveSpeed : CGFloat = 0.0 // 波紋速度
    
    var offsetX : CGFloat = 0.0 // 波浪 x 位移
    var currentWavePointY : CGFloat = 0.0 // 當前波浪上市高度Y(高度從大到小 座標系向下增長
    
    var variable : Float = 0.0 // 可變引數 更加真實 模擬波紋
    var increase : Bool = true // 增減變化
    
    var waterWaveWidth : CGFloat = 0.0 // 水波寬度
    
    override func awakeFromNib() {
        super.awakeFromNib()
        setUp()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUp()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUp()
    }
    
    private func setUp() {
        
        self.backgroundColor = UIColor.clearColor()
        firstWaveColor = UIColor.whiteColor()
        secondWaveColor = UIColor.whiteColor()
        dispatch_async(dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)) {
            self.startWave()
        }
        
        waveCycle =  2 * CGFloat(M_PI) / self.frame.size.width
        waterWaveWidth = UIScreen.mainScreen().bounds.size.width + 10
        
        waveSpeed = CGFloat(0.05 / M_PI)
        currentWavePointY = 0
        variable = 1.6
        increase = false
        offsetX = 0
    }
    
    func startWave() {
        if firstWaveLayer == nil {
            // 建立第一個波浪
            firstWaveLayer = CAShapeLayer()
            firstWaveLayer.fillColor = firstWaveColor.CGColor
            firstWaveLayer.opacity = 0.3
            self.layer.addSublayer(firstWaveLayer)
        }
        
        if secondWaveLayer == nil {
            // 建立第二個波浪
            secondWaveLayer = CAShapeLayer()
            secondWaveLayer.fillColor = secondWaveColor.CGColor
            self.layer.addSublayer(secondWaveLayer)
        }
        
        if waveDisplaylink == nil {
            // 啟動呼叫定時器
            waveDisplaylink = CADisplayLink(target: self, selector: #selector(getCurrentWave(_:)))
            waveDisplaylink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
        }
        
    }
    
    @objc private func getCurrentWave(displayLink: CADisplayLink) {
//        這裡是調整波浪狀態,自行發揮
//        if (increase) {
//            variable += 0.01
//        } else {
//            variable -= 0.01
//        }
//        if (variable <= 1) {
//            increase = true
//        }
//        
//        if (variable >= 1.6) {
//            increase = false
//        }
        
        waveAmplitude = CGFloat(variable * 2.5)
        offsetX += waveSpeed
        
        setCurrentFirstWaveLayerPath()
        
        setCurrentSecondWaveLayerPath()
    }
    
    private func setCurrentFirstWaveLayerPath() {
        let path = CGPathCreateMutable()
        var y = currentWavePointY
        var x : CGFloat = 0.0
        
        CGPathMoveToPoint(path, nil, 0, 0)
        while (true) {
            y = waveAmplitude * sin(waveCycle * x + offsetX) + currentWavePointY
            CGPathAddLineToPoint(path, nil, x, y)
            x += 1
            if x >= waterWaveWidth {
                break
            }
        }
        
        CGPathAddLineToPoint(path, nil, waterWaveWidth, self.frame.size.height)
        CGPathAddLineToPoint(path, nil, 0, self.frame.size.height)
        CGPathCloseSubpath(path)
       
        firstWaveLayer.path = path
    }
    
    private func setCurrentSecondWaveLayerPath() {
        let path = CGPathCreateMutable()
        var y = currentWavePointY
        var x : CGFloat = 0.0
        
        CGPathMoveToPoint(path, nil, 0, 0)
        while (true) {
            
            y = waveAmplitude * cos(waveCycle * x + offsetX) + currentWavePointY
            CGPathAddLineToPoint(path, nil, x, y)
            
            x += 1
            if x >= waterWaveWidth {
                break
            }
        }
        
        CGPathAddLineToPoint(path, nil, waterWaveWidth, self.frame.size.height)
        CGPathAddLineToPoint(path, nil, 0, self.frame.size.height)
        CGPathCloseSubpath(path)
        
        secondWaveLayer.path = path
    }
    
    deinit {
        reset()
    }
    
    private func reset() {
        if firstWaveLayer != nil {
            firstWaveLayer.removeFromSuperlayer()
            firstWaveLayer = nil
        }
        if secondWaveLayer != nil {
            secondWaveLayer.removeFromSuperlayer()
            secondWaveLayer = nil
        }
    }
    
}
複製程式碼

相關文章