最近做项目,项目中大量出现六边形视图,包括基本的视图和按钮。详情查看Demo
这种实现效果一般有两种
第一种:让美工小姐姐切图,使用iOS图片切片技术拉伸图片,但这种很有局限性,背景颜色,边框颜色,还有边框样式不一样就用切一种图片,非常不方便。
第二种:那就是使用贝塞尔曲线进行切割。这种方法优点非常明显,不管修改成什么颜色,边框样式都是可以的。
接下来我们来说一下第二种
切割六边形
1.首先我们来切割一下直角的六边形
在这里插入图片描述
extension UIView {
/// 切割六边形(没有弧度)
public func setSixRightBorder() {
/// 获取切割路径
let maskPath = getSexanglePath()
/// 创建切割路径Layer
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath
self.layer.mask = maskLayer
}
private func getSexanglePath() -> UIBezierPath {
let PI = CGFloat.pi
/// 整个视图的框
let allWidth = self.bounds.size.width
/// 整个视图的高
let allHeight = self.bounds.size.height
/// 我们假设六边形的内角是120度
let operateAngle = PI - 2*PI/3
/// 线段b的长度为
let bLength = allHeight/2
/// 所以如图线段a的长度为
let aLength = bLength/tan(operateAngle)
/// P1点坐标为
let p1 = CGPoint(x: allWidth - aLength, y: 0)
/// P2点坐标为
let p2 = CGPoint(x: allWidth, y: bLength)
/// P2点坐标为
let p3 = CGPoint(x: p1.x, y: allHeight)
/// 同理可求出 对应左边的3个点坐标
let p4 = CGPoint(x: aLength, y: allHeight)
/// P5点坐标为
let p5 = CGPoint(x: 0, y: bLength)
/// P6点坐标为
let p6 = CGPoint(x: aLength, y: 0)
let path = UIBezierPath()
path.move(to: p1)
path.addLine(to: p2)
path.addLine(to: p3)
path.addLine(to: p4)
path.addLine(to: p5)
path.addLine(to: p6)
path.close()
return path
}
}
20210309224845823.png
这里可以看到留个角是没有圆弧的,那么如何产生最上方效果图中的形状呢,接下来我们开始讲解
切割带弧度的六边形
20210309230212914.png这里是核心代码
/// 定义PI值
let PI = CGFloat(Double.pi)
/// 弧度半径
let radius: CGFloat = radius
/// 视图的宽
let allWidth = self.bounds.size.width
/// 视图的高
let allHeight = self.bounds.size.height
/// 视图高度的一半
let LayerHeigh = self.bounds.size.height/2
/// 六边形的一个内角度数(这里默认是正六边形 所以一个角是120度)
let sixDegree: CGFloat = PI*2/3
let operateDegree:CGFloat = PI - sixDegree
/// 圆弧与上边线的切点 到左上角的距离
let distance = radius / tan(operateDegree)
/// 左边定点到左上角之间的X狙击
let maxDistance = LayerHeigh / tan(operateDegree)
/// 计算第一个点
let firstPointX = allWidth - (maxDistance + distance)
let firstPoint = CGPoint(x: firstPointX, y: 0)
/// 计算第二个点
let secondPointX = firstPointX + distance + distance*cos(operateDegree)
let secondPointY = distance*sin(operateDegree)
let secondPoint = CGPoint(x: secondPointX, y: secondPointY)
/// 计算第三个点
let thirdPointX = allWidth - distance*cos(operateDegree)
let thirdPointY = LayerHeigh - distance*sin(operateDegree)
let thirdPoint = CGPoint(x: thirdPointX, y: thirdPointY)
/// 计算第四个点
let fourPointY = LayerHeigh + distance*sin(operateDegree)
let fourPoint = CGPoint(x: thirdPointX, y: fourPointY)
/// 计算第五个点
let fivePointY = allHeight - secondPoint.y
let fivePoint = CGPoint(x: secondPoint.x, y: fivePointY)
/// 计算第六个点
let sixPoint = CGPoint(x: firstPoint.x, y: allHeight)
/// 第七个点
let sevenPointX = maxDistance + distance
let sevenPoint = CGPoint(x: sevenPointX, y: allHeight)
/// 第八个点
let eightPointX = maxDistance - distance*cos(operateDegree)
let eightPoint = CGPoint(x: eightPointX, y: fivePointY)
/// 第九个点
let ninePointX = distance*cos(operateDegree)
let ninePoint = CGPoint(x: ninePointX, y: fourPointY)
/// 第十个点
let tenPoint = CGPoint(x: ninePointX, y: thirdPointY)
/// 第十一个点
let elevenPoint = CGPoint(x: eightPoint.x, y: secondPoint.y)
/// 第十二个点
let twelvePoint = CGPoint(x: sevenPoint.x, y: 0)
/// 第一个圆弧圆心坐标
let center1 = CGPoint(x: firstPoint.x, y: radius)
/// 第二个圆弧圆心坐标
let center2 = CGPoint(x: allWidth - distance/cos(operateDegree), y: LayerHeigh)
/// 第三个圆弧圆心坐标
let center3 = CGPoint(x: sixPoint.x, y: allHeight - radius)
/// 第四个圆弧圆心坐标
let center4 = CGPoint(x: sevenPoint.x, y: allHeight - radius)
/// 第五个圆弧圆心坐标
let center5 = CGPoint(x: distance/cos(operateDegree), y: LayerHeigh)
/// 第六个圆弧圆心坐标
let center6 = CGPoint(x: twelvePoint.x, y: radius)
let path = UIBezierPath()
path.move(to: firstPoint)
path.addArc(withCenter: center1, radius: radius, startAngle: CGFloat(-PI/2), endAngle: operateDegree - PI/2, clockwise: true)
path.addLine(to: thirdPoint)
path.addArc(withCenter: center2, radius: radius, startAngle: CGFloat(-operateDegree/2), endAngle: operateDegree/2, clockwise: true)
path.addLine(to: fivePoint)
path.addArc(withCenter: center3, radius: radius, startAngle: operateDegree/2, endAngle: PI/2, clockwise: true)
path.addLine(to: sevenPoint)
path.addArc(withCenter: center4, radius: radius, startAngle: PI/2, endAngle: PI/2 + operateDegree, clockwise: true)
path.addLine(to: ninePoint)
path.addArc(withCenter: center5, radius: radius, startAngle: PI - operateDegree/2, endAngle: PI + operateDegree/2, clockwise: true)
path.addLine(to: elevenPoint)
path.addArc(withCenter: center6, radius: radius, startAngle: PI + operateDegree/2, endAngle: PI*3/2, clockwise: true)
path.close()
效果图
20210309233032124.png
末尾附上Demo。如果你觉得有帮助,请多多Star,好了结束撒花,大家加油❀❀❀❀❀
网友评论