Swift :UIView扩展+直播间麦克风波纹扩散动画

功能需要,用贝塞尔曲线写了一个波纹动画分享一下

效果图:

在这里插入图片描述
知识点:

  1. 扩展不能直接加属性,用runtime方式添加
  //bord宽度  默认1.5
    var FQBordWith:CGFloat?{
        get{
            return (objc_getAssociatedObject(self,"FQBordWith") as? CGFloat)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQBordWith", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
  1. 注意 block 的循环引用 [weak self]
 self.FQTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(longTime), repeats: true, block: { [weak self](timer:Timer) in
            
            if let strongSelf = self { //精髓用法
                index += 1;
                if index > number {
                    strongSelf.invalidTimer()
                    return
                }
                strongSelf.start()
            }
            
        })

文件代码如下:

//
//  UIView+FQWave.swift
//  FQWaveDemo
//
//  Created by jiashiqi on 2020/4/7.
//  Copyright © 2020 jiashiqi. All rights reserved.
//

import Foundation
import UIKit

extension UIView{
    //bord宽度  默认1.5
    var FQBordWith:CGFloat?{
        get{
            return (objc_getAssociatedObject(self,"FQBordWith") as? CGFloat)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQBordWith", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    //动画时间 默认2
    var FQAnimationTime:CGFloat? {
        get{
            return (objc_getAssociatedObject(self,"FQAnimationTime") as? CGFloat)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQAnimationTime", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    //开始透明度 默认 0.8
    var FQStartAlph:CGFloat? {
        get{
            return (objc_getAssociatedObject(self,"FQStartAlph") as? CGFloat)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQStartAlph", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    
    //比例 默认1.5
    var FQScale:CGFloat? {
        get{
            return (objc_getAssociatedObject(self,"FQScale") as? CGFloat)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQScale", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    //颜色 默认red
    var FQColor:UIColor? {
        get{
            return (objc_getAssociatedObject(self,"FQColor") as? UIColor)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQColor", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    
    
    var FQTimer:Timer?{
        get{
            return (objc_getAssociatedObject(self,"FQTimer") as? Timer)
        }
        set(newValue){
            objc_setAssociatedObject(self, "FQTimer", newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    
    //开始动画
    public func startAnimation(circleNumber:NSInteger){
        if (self.FQTimer != nil) {
            self.invalidTimer()
        }
        var index = 0
        let number = circleNumber == 0 ? 1 : circleNumber
        // 每一个圈需要的时间
        let longTime:CGFloat = (self.FQAnimationTime ?? 2.0) / CGFloat(number)
        
        self.FQTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(longTime), repeats: true, block: { [weak self](timer:Timer) in
            
            if let strongSelf = self {
                index += 1;
                if index > number {
                    strongSelf.invalidTimer()
                    return
                }
                strongSelf.start()
            }
            
        })
    }
    //结束动画
    public func stopAnimation(){
        self.layer.removeAllAnimations()
        self.layer.superlayer?.perform(#selector(CALayer.removeFromSuperlayer))
        self.invalidTimer()
    }
    private func invalidTimer(){
        self.FQTimer?.invalidate();
        self.FQTimer = nil;
    }
    private func start(){
        
        //中心点
        let layer:CAShapeLayer = CAShapeLayer();
        layer.position = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2)
        layer.bounds = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
        layer.opacity = 0
        layer.backgroundColor = UIColor.clear.cgColor
        
        //画圆圈
        let path:UIBezierPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
        layer.path = path.cgPath
        layer.strokeColor = (self.FQColor ?? UIColor.red).withAlphaComponent((self.FQStartAlph ?? 0.8)).cgColor
        layer.lineWidth = (self.FQBordWith ?? 1.5)
        layer.fillColor = UIColor.clear.cgColor
        self.layer.addSublayer(layer)
        
        //动画
        //圈透明度
        let opacity:CABasicAnimation = CABasicAnimation(keyPath: "opacity")
        opacity.fromValue = (self.FQStartAlph ?? 0.8)
        opacity.toValue = 0
        
        //圈的发散
        let scale:CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
        scale.fromValue = 1.1
        scale.toValue = (self.FQScale ?? 1.5)
        
        //圈的宽度
        let border:CABasicAnimation = CABasicAnimation(keyPath: "lineWidth")
        border.fromValue = (self.FQBordWith ?? 1.5)
        border.toValue = 1
        border.duration = 0.2
        
        //动画组
        let animationGroup:CAAnimationGroup = CAAnimationGroup()
        animationGroup.animations = [opacity,scale,border]
        animationGroup.duration = CFTimeInterval(self.FQAnimationTime ?? 2.0)
        animationGroup.isRemovedOnCompletion = true;
        animationGroup.fillMode = CAMediaTimingFillMode.forwards;
        animationGroup.repeatCount = MAXFLOAT;
        layer.add(animationGroup, forKey: nil)
    }
}

dome下载:下载地址

如有问题,可留言解决。

原创文章 18 获赞 102 访问量 7948

猜你喜欢

转载自blog.csdn.net/weixin_46602773/article/details/105363219