iOS-绘制一个带动画的五角星图标

57 篇文章 1 订阅

GIF 示例:

这里写图片描述


具体实现步骤

计算五边形的五个点
温习三角函数

这里写图片描述

五边形各点计算图例:

这里写图片描述

代码示例:

1、使用延展,快速获取角度的 sin 和 cos 值

// MARK: - 延展 通过三角函数计算 con 和 sin 角度的值
extension CGFloat {
    // 通过角度获取 cos 值
    static func angleCosValue(_ angle: CGFloat) -> CGFloat {
        return CGFloat(cos(Double.pi/180.0 * Double(angle)))
    }

    // 通过角度获取 sin 值
    static func angleSinValue(_ angle: CGFloat) -> CGFloat {
        return CGFloat(sin(Double.pi/180.0 * Double(angle)))
    }
}

2、计算出中心点坐标和半径

// 中心的点
let centerX = bounds.size.width/2
let centerY = bounds.size.height/2

radius = centerX // 此处半径取画板的一般宽度

3、通过循环计算出多边形每个点的坐标并返回一个属性数组

// 通过 半径 获取五边形的五个点 return: 一个包含点数组
fileprivate func getPointWithRadius(radius: CGFloat) -> [NSValue] {
        // 保存每个点的 NSValue 数据
        var cornerPointsAttrs: [NSValue] = [NSValue]()
        // 多边形的边数
        let sideNum = 5
        // 计算多边形各个点的坐标
        // i为逆时针第i个点
        for i in 0..<sideNum {
            // 每个边长度所在的点

            // 计算每个点所在的坐标
            /*
             这里的 90.0 代表 第一个点是以 90 度 开始的, 即上图的 p0 位置是第一个点
             sideNum: 边数
             radius: 半径
             */
            /// 计算平均角度
            let avgsAngle: CGFloat = 360.0/CGFloat(sideNum)
            /// 计算每个点的 x 坐标
            let pointX: CGFloat = centerX-CGFloat.angleCosValue(90.0-avgsAngle*CGFloat(i))*radius
            /// 计算每个点的 y 坐标
            let pointY: CGFloat = centerY-CGFloat.angleSinValue(90.0-avgsAngle*CGFloat(i))*radius
            /// 将 x, y 坐标转换成 CGPoint 点
            let valuePoint = CGPoint(x: pointX, y: pointY)
            /// 将 每个点 转成 NSValue 类型并保存到属性数组中
            cornerPointsAttrs.append(NSValue(cgPoint: valuePoint))   
        }
        return cornerPointsAttrs
    }

4、通过坐标点属性数组,绘制点

// 通过点数组 - 绘制五个点
fileprivate func drawLineWithPoints(points: [NSValue]) {
        if points.count == 0 { return }
        // 循环画点
        for i in 0..<points.count {
            // 取出 位置 i 所在的点
            let point = points[i].cgPointValue
            // bezierPath 移动到点所在的位置
            bezierPath.move(to: point)
            // 在点所在的位置绘制一个圆,用于标记点
            bezierPath.addArc(withCenter: point, radius: 3, startAngle: CGFloat(-Double.pi/2), endAngle: CGFloat(-Double.pi/2.0001), clockwise: false)
        }
        // 绘制中心点
        let centerP = CGPoint(x: centerX, y: centerY)
        bezierPath.move(to: centerP)
        bezierPath.addArc(withCenter: centerP, radius: 3, startAngle: CGFloat(-Double.pi/2), endAngle: CGFloat(-Double.pi/2.0001), clockwise: false)
    }

5、将 bezierPath 路径赋值给 CAShapeLayer 完成图形的展示

override func layoutSubviews() {
        super.layoutSubviews()

        shapeLayer.frame = bounds
        shapeLayer.lineJoin = kCALineJoinRound
        shapeLayer.lineCap = kCALineCapRound
        shapeLayer.lineWidth = 2
        shapeLayer.strokeColor = UIColor.red.cgColor

        // 通过 shapeLayer 展示图像
        self.shapeLayer.path = self.bezierPath.cgPath
    }
绘制结果如图所示:

这里写图片描述


通过 UIBezierPath 连线 并 显示
1、将五个点连线
// 通过点数组连线 - 绘制五边形
fileprivate func drawLineWithPoints(points: [NSValue]) {
    if points.count == 0 { return }
    // 第一个点(也是最后一个点)
    let firstPoint = points[0].cgPointValue
    // 移动第一个点
    bezierPath.move(to: firstPoint)
    // 循环画点
    for i in 0..<points.count {
        // 取出 位置 i 所在的点
        let point = points[i].cgPointValue  
        bezierPath.addLine(to: point)
    }
    // 闭合路径,第一个点也是最后一个点
    bezierPath.addLine(to: firstPoint)
}
2、将 bezierPath 路径赋值给 CAShapeLayer 完成图形的展示

看上个步骤 5

绘制结果如图所示:

这里写图片描述


绘制圆形

具体实现请参考苹果官方文档

这里只展示一张角度图:

图片来自苹果官方文档

1、具体代码实现
/// 绘制圆形
fileprivate func drawCycle() {
    self.bezierPath.addArc(withCenter: CGPoint(x: centerX, y: centerY), radius: radius, startAngle: CGFloat(-Double.pi/2), endAngle: CGFloat(-Double.pi/2.0001), clockwise: false)
}
2、将 bezierPath 路径赋值给 CAShapeLayer 完成图形的展示

看上个步骤 5

绘制结果如图所示:

这里写图片描述


通过连线绘制星形
  • 通过五个点,连线即可绘制五角星
  • 连接顺序:p0–>p2–>p4–>p1–>p3–>p0
绘制五五角星
// 
fileprivate func drawFivePointedStar() {
    self.bezierPath.addLine(to: values[2].cgPointValue)
    self.bezierPath.addLine(to: values[4].cgPointValue)
    self.bezierPath.addLine(to: values[1].cgPointValue)
    self.bezierPath.addLine(to: values[3].cgPointValue)
    self.bezierPath.addLine(to: values[0].cgPointValue)
}
将 bezierPath 路径赋值给 CAShapeLayer 完成图形的展示

这里写图片描述


给路径添加动画
给CAShapeLayer 添加 CABasicAnimation 动画
/// 添加动画
fileprivate func addStrokeEndAnimationToLayer(layer: CAShapeLayer) {
    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = 0
    animation.toValue = 1
    animation.duration = 3
    layer.add(animation, forKey: "stokeEndAnimation")
}

最终运行结果示例:

这里写图片描述


over

Demo 传送门:传送门 –> DrawFivePointedStar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值