利用UIBezierPath貝塞爾曲線繪制圓角正多邊形遮罩

先上效果圖

正三角形

正方形

正五邊形

正六邊形

再上源碼

給UIView添加一個Category方法

/// 添加圓角正多邊形遮罩
/// @param viewWidth 當前視圖寬度
/// @param edgeCount 多邊形邊數(shù)
/// @param rotationAngle 旋轉(zhuǎn)角度
/// @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];

當然,也可以自由發(fā)揮做出像下面這樣的動效


旋轉(zhuǎn)
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容