如何在 Mac 上实现环形 loading 动画

2019-07-06  本文已影响0人  _我和你一样

如何在 Mac 上实现环形 loading 动画

网上也有很多 loading 动画,但每个公司的需求可能不同,网上找了很多可以在 Mac 上用的,要不和需求融入不方便吗,要么就是有很多多余的功能。

我们的需求不展示进度,展示的是几种状态,状态不同,执行的动画也不同。

我们状态共 4 种:

本想传个 gif 图的,没工具,下了个录不出效果。。。录了个视频,简书md 不支持。。。

下面说下实现思路:

通过自定义 NSView 来实现。主要用到绘图相关的知识。

各个状态的动画分别实现,代码不多,注释很详细,不啰嗦了。

import Cocoa

class LoadingView: NSView {
    
    private var animationLayer:CAShapeLayer!
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        basicInit()
    }
    
    required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
        basicInit()
    }
    
    private func basicInit() {
        wantsLayer = true
        animationLayer = CAShapeLayer()
        layer?.addSublayer(animationLayer)
        animationLayer.frame = bounds
        // 画圆
        let path = CGMutablePath()
        let center = CGPoint(x: bounds.width/2, y: bounds.height/2)
        path.addArc(center: center, radius: 0.9 * bounds.width/2, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true)
        animationLayer.path = path
        // 画边框(r:0.20 g:0.85 b:0.99 a:1.00)
        animationLayer.strokeColor = CGColor(red: 0.20, green: 0.85, blue: 0.99, alpha: 1.00)
        animationLayer.lineWidth = 5
        animationLayer.fillColor = NSColor.clear.cgColor// 清空填充颜色
        
        // 画部分圆环
        animationLayer.strokeEnd = 0.2
        animationLayer.isHidden = true
        // 动画在需要时进行调用
    }
    
    
    
    // 连接动画
    func connectingAnimation() {
        animationLayer.isHidden = false
        animationLayer.removeAllAnimations()
        let rotateAnimtion = CABasicAnimation(keyPath: "transform.rotation.z")
        let startValue = NSNumber(value: Float(2.0*CGFloat.pi))
        let endValue = NSNumber(value: 0)
        rotateAnimtion.fromValue = startValue
        rotateAnimtion.toValue = endValue
        rotateAnimtion.duration = 1
        rotateAnimtion.repeatCount = Float(CGFloat.greatestFiniteMagnitude)
        animationLayer.add(rotateAnimtion, forKey: "connecting")
    }
    
    // 连接成功动画
     func concectedAnimation() {
        animationLayer.isHidden = false
        let connectedAnimation = CABasicAnimation(keyPath: "strokeEnd")
        connectedAnimation.fromValue = NSNumber(value: 0.2)
        connectedAnimation.toValue = NSNumber(value: 1)
        connectedAnimation.duration = 1
        connectedAnimation.delegate = self
        animationLayer.add(connectedAnimation, forKey: "connected")
    }
    
    // 断开动画
    func disconcectAnimation() {
        animationLayer.isHidden = false
        let connectedAnimation = CABasicAnimation(keyPath: "strokeEnd")
        connectedAnimation.toValue = NSNumber(value: 0)
        connectedAnimation.duration = 0.5
        connectedAnimation.delegate = self
        connectedAnimation.fillMode = .forwards
        connectedAnimation.isRemovedOnCompletion = false
        animationLayer.add(connectedAnimation, forKey: "disconcect")
    }
    
    
    // 断开中动画
     func disconnectingAnimation() {
        animationLayer.isHidden = false
        animationLayer.removeAllAnimations()
        let rotateAnimtion = CABasicAnimation(keyPath: "transform.rotation.z")
        let startValue = NSNumber(value: Float(2.0*CGFloat.pi))
        let endValue = NSNumber(value: 0)
        rotateAnimtion.fromValue = endValue
        rotateAnimtion.toValue = startValue
        rotateAnimtion.duration = 1
        rotateAnimtion.repeatCount = Float(CGFloat.greatestFiniteMagnitude)
        animationLayer.add(rotateAnimtion, forKey: "disconnecting")
    }
}

extension LoadingView:CAAnimationDelegate {
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        animationLayer.isHidden = true
        animationLayer.removeAllAnimations()
    }
}

上一篇 下一篇

猜你喜欢

热点阅读