具体动画
如上图,动画可以拆分为三部分
- 1 . 中间扇叶的旋转动画!
- 2 . 两边的画线轨迹!
- 3 . 动态变化的进度显示!
中间扇叶动画
我这边使用的4张图片,已附上:
很明显了是吧,只需要把图片加上去,然后旋转起来就可以了。
那么怎么让它变成旋转的呢?其实很简单,Apple 就已经提供给我们很好的API 以供使用!
图片旋转
声明部分
/// 菊花视图
lazy var hudImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "bgImage")
return imageView
}()
///叶子视图1
lazy var imageView1: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "image01")
return imageView
}()
///叶子视图2
lazy var imageView2: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "image02")
return imageView
}()
///叶子视图3
lazy var imageView3: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "image03")
return imageView
}()
/// 初始旋转角度
var angleHud = CGFloat(1);
var angle1 = CGFloat(1);
var angle2 = CGFloat(1);
var angle3 = CGFloat(1);
/// 是否停止动画
var isStop = false
旋转图片实现方法
/// 开始图片动画
private func startImageView(){
//选择动画:
let endAnglehud = CGAffineTransform(rotationAngle: angleHud * .pi / 180)
let endAngle1 = CGAffineTransform(rotationAngle: angle1 * .pi / 180)
let endAngle2 = CGAffineTransform(rotationAngle: angle2 * .pi / 180)
let endAngle3 = CGAffineTransform(rotationAngle: angle3 * .pi / 180)
UIView.animate(withDuration: 0.01) {
self.hudImageView.transform = endAnglehud
self.imageView1.transform = endAngle1
self.imageView2.transform = endAngle2
self.imageView3.transform = endAngle3
} completion: { finished in
self.angleHud -= 4;
self.angle1 += 4;
self.angle2 -= 4;
self.angle3 += 4;
//
if !self.isStop {
self.startImageView()
}
}
}
图片旋转实现并不难,直接使用就可以了,如上
然后需要旋转多少,速度都可以更改以上的参数进行自己喜好调整
UI加载部分
/// 菊花内容 - 宽高
let hudSize = CGSize(width: 120, height: 120)
/// 进度Lable
lazy var progressLable: UILabel = {
let lable = UILabel()
lable.textColor = mainColor
lable.font = UIFont.systemFont(ofSize: 12)
lable.textAlignment = .center
lable.text = "0%"
return lable
}()
/// 主颜色
let mainColor = UIColor(red: 239/255, green: 223/255, blue: 183/255, alpha: 1)
// MARK: - UI实现
func loadUI() -> Void {
self.addSubview(bgImageView)
bgImageView.addSubview(imageView1)
bgImageView.addSubview(imageView2)
bgImageView.addSubview(imageView3)
bgImageView.addSubview(hudImageView)
bgImageView.addSubview(progressLable)
}
override func layoutSubviews() {
super.layoutSubviews()
bgImageView.frame = self.bounds
imageView1.center = bgImageView.center
imageView1.frame.size = hudSize
imageView2.center = bgImageView.center
imageView2.frame.size = hudSize
imageView3.center = bgImageView.center
imageView3.frame.size = hudSize
hudImageView.center = bgImageView.center
hudImageView.frame.size = hudSize
progressLable.center = bgImageView.center
progressLable.frame.size = CGSize(width: 50, height: 50)
progressLable.layer.cornerRadius = progressLable.frame.height/2
progressLable.layer.masksToBounds = true
progressLable.layer.borderColor = progressLable.textColor.cgColor
progressLable.layer.borderWidth = 0.8
}
以上实现就不需要过多叙述了,进度的使用的是一个Lable.
那么说下,最后一个,前言说到的画线轨迹动画!
很明显,动画轨迹来看,一个直线和一个半圆,
既然如此,那么就可以按照这个想法来进行实现!我们都知道,iOS中有个很强大的类,UIBezierPath
轨迹画线!
可供参考的 :
UIBezierPath苹果官方API文献
李国安的文章
下面就是代码实现部分,先贴代码:
/// 重写系统 绘制方法
override func draw(_ rect: CGRect) {
///上半部轨迹
let path = UIBezierPath()
//起点
path.move(to: CGPoint(x: self.frame.width, y: self.center.y))
//直线终点
path.addLine(to: CGPoint(x: self.center.x+hudSize.width/2, y: self.center.y))
path.addArc(withCenter: self.center, radius: 60, startAngle: .pi*2, endAngle: .pi*1, clockwise: false)
let caShapelayer = CAShapeLayer()
caShapelayer.path = path.cgPath
//线条宽度
caShapelayer.lineWidth = 1.5
//线条颜色
caShapelayer.strokeColor = mainColor.cgColor
//填充颜色
caShapelayer.fillColor = UIColor.clear.cgColor
caShapelayer.frame = self.bounds
self.layer.addSublayer(caShapelayer)
///下半部轨迹
let path2 = UIBezierPath()
//起点
path2.move(to: CGPoint(x: 0, y: self.center.y))
//直线终点
path2.addLine(to: CGPoint(x: self.center.x-hudSize.width/2, y: self.center.y))
path2.addArc(withCenter: self.center, radius: 60, startAngle: .pi*1, endAngle: .pi*2, clockwise: false)
let caShapelayer2 = CAShapeLayer()
caShapelayer2.path = path2.cgPath
//线条宽度
caShapelayer2.lineWidth = 1.5
//线条颜色
caShapelayer2.strokeColor = mainColor.cgColor
//填充颜色
caShapelayer2.fillColor = UIColor.clear.cgColor
caShapelayer2.frame = self.bounds
self.layer.addSublayer(caShapelayer2)
DispatchQueue.main.async {
self.drawLineAnimation(layer: caShapelayer)
self.drawLineAnimation(layer: caShapelayer2)
}
}
/// 轨迹动画添加到Self- 轨迹动画
func drawLineAnimation(layer:CALayer) -> Void {
let bas = CABasicAnimation.init(keyPath: "strokeEnd")
bas.duration = 3
bas.delegate = self
bas.fromValue = 0
bas.toValue = 1
layer.add(bas, forKey: "key")
}
总体来说,上下部分轨迹,实际上是一样的,所以就分析其中一个就可以了,首先,确定path 轨迹起点,拐点,和终点!
///上半部轨迹
let path = UIBezierPath()
//起点
path.move(to: CGPoint(x: self.frame.width, y: self.center.y))
//直线终点
path.addLine(to: CGPoint(x: self.center.x+hudSize.width/2, y: self.center.y))
//圆路径
path.addArc(withCenter: self.center, radius: 60, startAngle: .pi*2, endAngle: .pi*1, clockwise: false)
直线路径无需多说,注释已经很清晰了,主要说下,半圆轨迹:
系统方法
open func addArc(withCenter center: CGPoint,
radius: CGFloat,
startAngle: CGFloat,
endAngle: CGFloat,
clockwise: Bool)
-
center
: 顾名思义就是圆的中心点,学过数学的都知道! -
radius
: 圆的半径! -
startAngle
: 圆轨迹起始的弧度! -
endAngle
: 圆轨迹结束的弧度! -
clockwise
: 是否顺时针!
封装API,提供外部使用
/// 单例
static let shareView = AnimationLoadView()
/// 快捷初始化
public static func show() -> Void{
let window = UIApplication.shared.delegate?.window!
shareView.backgroundColor = .black
shareView.frame = UIScreen.main.bounds
window!.addSubview(shareView)
shareView.start()
}
/// 开始动画
public func start() -> Void {
startImageView()
}
/// 结束动画
public func stop() -> Void {
isStop = true
progressLable.text = "0%"
self.angleHud = 1;
self.angle1 = 1;
self.angle2 = 1;
self.angle3 = 1;
self.removeFromSuperview()
}
至此所有的动画效果都已经完成,在有需要的地方进行调用,就可以了!
ps: 不当之处还请海涵,分享以及记录自己的代码,请不喜勿喷!