美文网首页
利用UIBezierPath贝塞尔曲线绘制圆角正多边形遮罩

利用UIBezierPath贝塞尔曲线绘制圆角正多边形遮罩

作者: _moses | 来源:发表于2020-10-13 19:12 被阅读0次

先上效果图

正三角形
正方形
正五边形
正六边形

再上源码

给UIView添加一个Category方法

/// 添加圆角正多边形遮罩
/// @param viewWidth 当前视图宽度
/// @param edgeCount 多边形边数
/// @param rotationAngle 旋转角度
/// @param cornerRadius 圆角半径(0 - cos(M_PI / edgeCount) * viewWidth)
- (void)addRoundedPolygonMaskWithViewWidth:(CGFloat)viewWidth edgeCount:(NSInteger)edgeCount rotationAngle:(CGFloat)rotationAngle cornerRadius:(CGFloat)cornerRadius {
    
    NSAssert(viewWidth > 0, @"viewWidth出错");
    NSAssert(edgeCount >= 3, @"edgeCount出错");
    NSAssert(cornerRadius >= 0, @"cornerRadius出错");
    NSAssert(cornerRadius / viewWidth <= cos(M_PI / edgeCount), @"cornerRadius出错");
    
    CGFloat viewRadius = viewWidth / 2.0;
    UIBezierPath *path = [UIBezierPath bezierPath];
    CGFloat angleCoefficient = M_PI / 180.0;
    CGFloat averageAngle = M_PI / edgeCount;
    CGFloat averageAngle2 = 360.0 / edgeCount;
    if (cornerRadius) {
        for (int i = 0; i < edgeCount; i++) {
            CGFloat angle = (rotationAngle + averageAngle2 / 2.0 + i * averageAngle2) * angleCoefficient;
            CGFloat centerRadius = viewRadius - cornerRadius / sin(M_PI_2 - averageAngle);
            CGFloat tempSide1 = sin(averageAngle) * centerRadius;
            CGFloat tempSide2 = cos(averageAngle) * viewRadius;
            CGFloat pointRadius = sqrt(tempSide1 * tempSide1 + tempSide2 * tempSide2);
            CGFloat pointAngle = averageAngle - atan(tempSide1 / tempSide2);
            CGPoint point = CGPointMake(viewRadius - pointRadius * sin(angle - pointAngle), viewRadius + pointRadius * cos(angle - pointAngle));
            CGPoint centerPoint = CGPointMake(viewRadius - centerRadius * sin(angle), viewRadius + centerRadius * cos(angle));
            CGFloat startAngle = (90 + rotationAngle + i * averageAngle2) * angleCoefficient;
            if (i) {
                [path addLineToPoint:point];
            } else {
                [path moveToPoint:point];
            }
            [path addArcWithCenter:centerPoint radius:cornerRadius startAngle:startAngle endAngle:startAngle + averageAngle * 2 clockwise:YES];
        }
    } else {
        for (int i = 0; i < edgeCount; i++) {
            CGFloat angle = (rotationAngle + averageAngle2 / 2.0 + i * averageAngle2) * angleCoefficient;
            CGPoint point = CGPointMake(viewRadius * (1 - sin(angle)), viewRadius * (1 + cos(angle)));
            if (i) {
                [path addLineToPoint:point];
            } else {
                [path moveToPoint:point];
            }
        }
    }
    [path closePath];
    CAShapeLayer *shapLayer = [CAShapeLayer layer];
    shapLayer.path = path.CGPath;
    self.layer.mask = shapLayer;
}

最后上测试用例

先添加两张图片,一个背景,一个头像(效果在头像上,背景不是必要的,只是为了形成明显对比才加的背景)

UIImageView *back = [[UIImageView alloc] init];
back.image = [UIImage imageNamed:@"back"];
back.frame = CGRectMake(0, 0, 375, 667);
[self.view addSubview:back];

UIImageView *header = [[UIImageView alloc] init];
header.image = [UIImage imageNamed:@"header"];
header.frame = CGRectMake(100, 300, 175, 175);
[self.view addSubview:header];

上面效果图中四个正三角形对应的方法

[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:3 rotationAngle:0 cornerRadius:0];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:3 rotationAngle:0 cornerRadius:10];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:3 rotationAngle:0 cornerRadius:20];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:3 rotationAngle:60 cornerRadius:10];

上面效果图中四个正方形对应的方法

[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:4 rotationAngle:0 cornerRadius:0];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:4 rotationAngle:0 cornerRadius:10];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:4 rotationAngle:0 cornerRadius:20];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:4 rotationAngle:45 cornerRadius:20];

上面效果图中四个正五边形对应的方法

[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:5 rotationAngle:0 cornerRadius:0];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:5 rotationAngle:0 cornerRadius:10];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:5 rotationAngle:0 cornerRadius:20];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:5 rotationAngle:36 cornerRadius:20];

上面效果图中四个正六边形对应的方法

[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:6 rotationAngle:0 cornerRadius:0];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:6 rotationAngle:0 cornerRadius:10];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:6 rotationAngle:0 cornerRadius:20];
[header addRoundedPolygonMaskWithViewWidth:175 edgeCount:6 rotationAngle:30 cornerRadius:20];

当然,也可以自由发挥做出像下面这样的动效


旋转

相关文章

网友评论

      本文标题:利用UIBezierPath贝塞尔曲线绘制圆角正多边形遮罩

      本文链接:https://www.haomeiwen.com/subject/xhfbpktx.html