美文网首页动画Swift
Swift加载动画多球旋转

Swift加载动画多球旋转

作者: 四月_Hsu | 来源:发表于2018-11-21 15:31 被阅读61次

1、用于网络请求、WebView的加载动画,效果如下图:

加载图

源码中有大量注释。Demo地址

1.1 实现思路

绘制三个球,给每个球添加动画组。以其中一个为例:

    /// 开启第一个小球动画
    private func startOneBallAnimation() {
        // 旋转动画
        let transformation = CAKeyframeAnimation(keyPath: "transform.translation.z")
        transformation.values = [0, 1, 0, 0]
        
        // 第一个小球位移动画
        let oneFrameAnimation = CAKeyframeAnimation(keyPath: "position")
        let path = CGMutablePath.init()
        path.move(to:  CGPoint(x: centerPoint.x - distance, y: centerPoint.y))
        path.addLine(to: CGPoint(x: centerPoint.x, y: centerPoint.y))
        path.addLine(to:  CGPoint(x: centerPoint.x + distance, y: centerPoint.y))
        path.addLine(to:  CGPoint(x: centerPoint.x - distance, y: centerPoint.y))
        oneFrameAnimation.path = path
        oneFrameAnimation.keyTimes = [0, 0.333333, 0.666666, 1.0] as [NSNumber]
        
        // 第一个小球缩放动画
        let oneScaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
        oneScaleAnimation.values = [0.7, 1.2, 0.7, 0.7]
        
        // 第一个小球透明动画
        let oneOpactiyAniamtion = CAKeyframeAnimation(keyPath: "opacity")
        
        // 组合动画
        let oneGroup = CAAnimationGroup()
        oneGroup.animations = [transformation, oneFrameAnimation, oneScaleAnimation, oneOpactiyAniamtion]
        oneGroup.duration = self.animationDurtion
        oneGroup.repeatCount = HUGE
        oneLayer.add(oneGroup, forKey: "oneGroup")
    }
1.2 对外接口,设置动画属性:
// MARK: - Public Methods
    /// 设置小球半径
    func setBallRadius(radius: CGFloat) {
        self.radius = radius
        oneLayer.path = UIBezierPath(arcCenter: centerPoint, radius: radius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true).cgPath
        twoLayer.path = UIBezierPath(arcCenter: centerPoint, radius: radius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true).cgPath
        threeLayer.path = UIBezierPath(arcCenter: centerPoint, radius: radius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true).cgPath
    }

    /// 设置三个小球颜色
    func setBallColor(firstColor: UIColor, secondColor: UIColor, thirdColor: UIColor) {
        oneLayer.fillColor = firstColor.cgColor
        twoLayer.fillColor = secondColor.cgColor
        threeLayer.fillColor = thirdColor.cgColor
    }
    
    /// 设置动画时长
    func setAnimationDurtion(durtion: TimeInterval) {
        self.animationDurtion = durtion
    }
    
    /// 设置小球移动轨迹的半径
    func setAnimatonDistance(distance: CGFloat) {
        self.distance = distance
        if distance > bounds.width || distance < 4 {
            self.distance = bounds.width / 2
        }
    }
    
    /// 开始动画
    func startAnimation() {
        stopAnimation()
        
        startOneBallAnimation()
        startTwoBallAnimation()
        startThreeBallAnimation()
    }
    
    /// 结束动画
    func stopAnimation() {
        // 不需要吧,这里又没有影响性能的
        oneLayer.removeAllAnimations()
        twoLayer.removeAllAnimations()
        threeLayer.removeAllAnimations()
    }
1.3 给UIView写扩展,用户加载动画。makeLoading(title: String? = "", enable: Bool = false), 如果有title,则特殊展示,没有则只展示动画。enable标识动画展示期间界面是否可进行点击操作。
extension UIView {
    /// 添加加载动画
    ///
    /// - Parameters:
    ///   - title: 描述文字
    ///   - enable: 加载期间是否可执行其他操作
    func makeLoading(title: String? = "", enable: Bool = false) {
        // 加载图基本展示
        var roundView: HsuBallRoatationView?
        var needInitRoundView = true
        var needInitCoverView = true
        var needInitTitleView = true
        subviews.forEach { (v) in
            if v.tag == 10001 {
                needInitRoundView = false
            }
            if v.tag == 10002 {
                needInitCoverView = false
            }
            if v.tag == 10003 {
                needInitTitleView = false
            }
        }
        if needInitRoundView {
            roundView = HsuBallRoatationView(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
        }
        guard let rView = roundView else {
            return
        }
        rView.center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
        rView.tag = 10001
        addSubview(rView)
        bringSubviewToFront(rView)
        rView.backgroundColor = UIColor.clear
        
        // 如果有文本
        if title != nil && !title!.isEmpty && needInitTitleView {
            let fontSize:CGFloat = 16
            let strSize = (title! as NSString).boundingRect(with: CGSize(width: bounds.width - 50, height: 15), options: [], attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)], context: nil).size
            
            let titleView = UIView(frame: CGRect(x: 0, y: 0, width: strSize.width > 100 ? strSize.width + 25 : 100, height: 80))
            titleView.backgroundColor = UIColor.groupTableViewBackground
            titleView.clipsToBounds = true
            titleView.layer.cornerRadius = 10
            titleView.center =  CGPoint(x: bounds.width / 2, y: bounds.height / 2)
            addSubview(titleView)
            bringSubviewToFront(titleView)
            titleView.tag = 10003
            
            rView.removeFromSuperview()
            rView.center = CGPoint(x: titleView.bounds.width / 2, y: 20)
            titleView.addSubview(rView)
            
            // 添加标题
            let label = UILabel(frame: CGRect(x: 0, y: 0, width: strSize.width, height: 20))
            label.text = title
            label.font = UIFont.systemFont(ofSize: fontSize)
            label.backgroundColor = UIColor.clear
            label.textColor = UIColor.darkGray
            label.textAlignment = .center
            titleView.addSubview(label)
            label.center = CGPoint(x: titleView.bounds.width / 2, y: titleView.bounds.height - 18)
        }
        
        // 如果不可点击,则在高层添加遮罩
        if !enable {
            if needInitCoverView {
                let coverView = UIControl(frame: bounds)
                coverView.isEnabled = true
                coverView.tag = 10002
                addSubview(coverView)
                bringSubviewToFront(coverView)
            }
        }
    }
    
    /// 移除加载动画
    func dismissLoading() {
        subviews.forEach { (v) in
            if v.tag == 10001 {
                v.removeFromSuperview()
            }
            if v.tag == 10002 {
                v.removeFromSuperview()
            }
            if v.tag == 10003 {
                v.removeFromSuperview()
            }
        }
    }
}

2、最终效果如下图

效果图

相关文章

  • Swift加载动画多球旋转

    1、用于网络请求、WebView的加载动画,效果如下图: 源码中有大量注释。Demo地址 1.1 实现思路 绘制三...

  • android自定义View索引

    一:加载动画 1:android仿qq下拉刷新旋转白条加载动画 2:android常用旋转线条加载动画 ...

  • 动画代码

    图片旋转动画 Swift3.0为视图添加旋转动画_CABasicAnimation

  • 旋转加载动画

    1.自定义UIImageView UIImageView *loadingImage = [[UIImageVie...

  • ionic 加载动画+选项卡栏操作

    ionic 加载动画 ion-spinner ionSpinner 提供了许多种旋转加载的动画图标。当你的界面加载...

  • CABasicAnimation动画页面跳转返回后停止

    之前把一张图片旋转来做了一个加载动画,但发现动画在加载时跳转了页面返回后没加载完成动画也停止了。 把动画的auto...

  • 【iOS】- Swift 旋转+轨迹动画制作加载页面

    具体动画1242701-bc21f72752a5d367.gif 如上图,动画可以拆分为三部分1 . 中间扇叶的旋...

  • 图片动画

    把一张图片旋转来做了一个加载动画,但发现动画在加载时跳转了页面返回后没加载完成动画也停止了 方案一: CABasi...

  • 圆环旋转加载动画

    给需要的朋友,思路还是比较简单,代码比较直接,没有封装,复制粘贴即可看到效果。 (void)creatText{N...

  • 正在加载之8个圆球动画旋转

    显示8个圆球围成一个圆形的动画加载效果,类似一个实心球带着拖尾旋转只需要绘制8个实心圆球外加8个无限动画触发圆球的...

网友评论

    本文标题:Swift加载动画多球旋转

    本文链接:https://www.haomeiwen.com/subject/uyhcqqtx.html