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