Swift实现一个简单的加载动画,以及动画的详解

一.组动画的创建

首先创建一个组动画,也就是大小变化和透明度变化的动画。

// 大小变化
        let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")

        scaleAnimation.keyTimes = [0, 0.5, 1]
        scaleAnimation.values = [1, 0.4, 1]
        scaleAnimation.duration = duration

        // 透明度变化
        let opacityAnimaton = CAKeyframeAnimation(keyPath: "opacity")
        //该属性是一个数组,用以指定每个子路径的时间。
        opacityAnimaton.keyTimes = [0, 0.5, 1]
        //values属性指明整个动画过程中的关键帧点,需要注意的是,起点必须作为values的第一个值。
        opacityAnimaton.values = [1, 0.3, 1]
        opacityAnimaton.duration = duration

        // 组动画
        let animation = CAAnimationGroup()
        //将大小变化和透明度变化的动画加入到组动画
        animation.animations = [scaleAnimation, opacityAnimaton]
        //动画的过渡效果
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        //动画的持续时间
        animation.duration = duration
        //设置重复次数,HUGE可看做无穷大,起到循环动画的效果
        animation.repeatCount = HUGE
        //运行一次是否移除动画
        animation.removedOnCompletion = false

需要注意的是上面的animation.timingFunction是动画的过渡效果,里面有这几种,你可以根据自己的需求选择
1. kCAMediaTimingFunctionLinear//线性
2. kCAMediaTimingFunctionEaseIn//淡入
3. kCAMediaTimingFunctionEaseOut//淡出
4. kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
5. kCAMediaTimingFunctionDefault//默认

二.创建圆形图层

  // Draw circles
        for var i = 0; i < 8; i++ {
            let circle = creatCircle(angle: CGFloat(M_PI_4 * Double(i)),
                size: circleSize,
                origin: CGPoint(x: x, y: y + 50),
                containerSize: size,
                color: color)
            animation.beginTime = beginTime + beginTimes[i]
            circle.addAnimation(animation, forKey: "animation")
            layer.addSublayer(circle)
        }

这里面是创建了八个小圆,将组动画赋予这八个圆,并添加在这个视图的Layer上,creatCircle 创图层的这个方法如下

 func creatCircle(# angle: CGFloat, size: CGFloat, origin: CGPoint, containerSize: CGSize, color: UIColor) -> CALayer {
        let radius = containerSize.width/2
        let circle = createLayerWith(size: CGSize(width: size, height: size), color: color)
        let frame = CGRect(
            x: origin.x + radius * (cos(angle) + 1) - size / 2,
            y: origin.y + radius * (sin(angle) + 1) - size / 2,
            width: size,
            height: size)
        circle.frame = frame

        return circle

    }

上面anglesizeorigincontainerSizecolor,都是传入的参数,-> CALayer 这个在Swift中代表的是返回类型,这里的返回类型就是CALayer,不像在OC中返回类型写在方法的前面- (CALayer *) ...
这里func creatCircle(# angle: CGFloat,里面有#,代表的就是在函数(或者方法)的参数名前添加”#”,可以使该参数拥有相同的本地参数名和外部参数名。(注:在方法中,第二个及后续的参数,默认是具有和内部参数一致的外部参数名的,只有第一个参数没有,可以使用”#”符号来强制给第一个参数添加与本地参数名一致的外部参数名,但是不推荐。)

三.创建CAShapeLayer

也就是上面的createLayerWith这个方法,如下

 func createLayerWith(# size: CGSize, color: UIColor) -> CALayer {
        //创建CAShapeLayer,如果对CAShapeLayer比较陌生,简单介绍下CAShapeLayer
        let layer: CAShapeLayer = CAShapeLayer()
        //创建贝塞尔曲线路径(CAShapeLayer就依靠这个路径渲染)
        var path: UIBezierPath = UIBezierPath()
        //addArcWithCenter,顾名思义就是根据中心点画圆(OC语法的命名优越感又体现出来了0.0),这几个参数
        /**
        center: CGPoint 中心点
        radius: CGFloat 半径
        startAngle: CGFloat 起始的弧度
        endAngle: CGFloat 结束的弧度
        clockwise: Bool 绘画方向 true:顺时针 false:逆时针
        */
        path.addArcWithCenter(CGPoint(x: size.width / 2, y: size.height / 2),
                radius: size.width / 2,
                startAngle: 0,
                endAngle: CGFloat(2 * M_PI),
                clockwise: false);
        //线宽,如果画圆填充的话也可以不设置
        layer.lineWidth = 2
        //填充颜色,这里也就是圆的颜色
        layer.fillColor = color.CGColor
        //图层背景色
        layer.backgroundColor = nil
        //把贝塞尔曲线路径设为layer的渲染路径
        layer.path = path.CGPath

        return layer;
    }

CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图形,最后CAShapeLayer就自动渲染出来了。当然,你也可以用Core Graphics直接向原始的CALyer的内容中绘制一个路径,相比直下,使用CAShapeLayer有以下一些优点:

  1. 渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。
  2. 高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形(CALyercontents属性,如果要给contents赋值就是layer.contents = (__bridge id)image.CGImage,所以占用内存大),所以无论有多大,都不会占用太多的内存。
  3. 不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉。
  4. 不会出现像素化。当你给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。

到此,运行我们就可以看到效果了,如下
这里写图片描述
代码可在#这里#下载。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的按钮动画示例,使用Swift语言编写: ```swift import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 创建按钮 let button = UIButton(frame: CGRect(x: 0, y: 0, width: 200, height: 50)) button.center = view.center button.setTitle("点击", for: .normal) button.setTitleColor(.white, for: .normal) button.backgroundColor = .blue button.layer.cornerRadius = button.frame.height / 2 button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) view.addSubview(button) // 添加按钮动画 let animation = CABasicAnimation(keyPath: "backgroundColor") animation.fromValue = UIColor.blue.cgColor animation.toValue = UIColor.red.cgColor animation.duration = 1.0 animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) animation.autoreverses = true animation.repeatCount = Float.infinity button.layer.add(animation, forKey: "backgroundColor") } @objc func buttonTapped() { print("按钮被点击了!") } } ``` 这个示例中,我们创建了一个蓝色背景、白色文字的按钮,并给它添加了一个圆形的圆角。然后,我们使用`CABasicAnimation`类创建了一个简单动画,将按钮的背景颜色从蓝色渐变到红色,并在完成后自动反转。最后,我们将动画添加到按钮的图层上,并在无限重复中运行。 当用户点击按钮时,`buttonTapped()`方法将被调用,我们在这个示例中只是简单地打印一条消息。你可以根据你的需要更改这个方法,以执行其他操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值