UIBezierPath画不规则图形

小试牛刀

效果图是一个圆角矩形加一个尖角三角形,我称之为尖角矩形,如下图所示

image1.png

直接要设计师提供一个切图当然是非常简单的,而且毫无难度。

但是刚好前两天看到一个效果,使用UIBezierPath画的一个下拉刷新的效果,这会想想是否能不用图片,使用UIBezierPath来画这个效果。

说干就干。

背景区域整体大小为,宽140,高50,尖角区域长度为20

        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(20, 0)];
        [path addLineToPoint:CGPointMake(0, 25)];
        [path addLineToPoint:CGPointMake(20, 50)];
        [path addLineToPoint:CGPointMake(140, 50)];
        [path addLineToPoint:CGPointMake(140, 0)];
        [path closePath];
        
        CAShapeLayer *layer = [CAShapeLayer layer];
        layer.path = path.CGPath;
        layer.fillColor = UIColorFromRGB(0xFFEEE8).CGColor;
        [rightBgView.layer insertSublayer:layer atIndex:0];

轻轻松松,效果实现。

进阶效果

经过初级实验,使用UIBezierPath绘制不规则图形还蛮简单,有一个复杂的效果,也考虑自己绘制。效果图如下

image2.png

根据和设计师沟通,得知右边为一个圆角矩形,左下角为一个不规则图形,类似一个矩形,裁切掉一个椭圆后剩下的一个边角(设计师画的一个三角形,然后将一条边拉成弧形,如下图所示)

image3.png

既然拆分成圆角矩形和另外一个不规则图形,就使用两个UIBezierPath来分别绘制,第一步,圆角矩形,这个很容易

    // 根据内容取得文字宽度,已设置按钮的contentEdgeInserts
    CGFloat width = _tipsButton.intrinsicContentSize.width;
    // 此处要用设置的高度20,而不能取内容高度
    CGFloat height = 20;
    // 左边不规则图形宽度
    CGFloat flex = 12;
    // 将效果拆分,一个是矩形圆角,一个是不规则色块
    UIBezierPath *path1 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(flex, 0, width-flex, height) byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomRight cornerRadii:CGSizeMake(4, 4)];

    CAShapeLayer *tipsLayer = [CAShapeLayer layer];
    tipsLayer.path = path1.CGPath;
    tipsLayer.fillColor = UIColorFromRGB(0xFFEEE8).CGColor;
    [_tipsButton.layer insertSublayer:tipsLayer atIndex:0];

第二步,不规则图形,使用了二阶贝塞尔曲线

    // 不规则图形
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(0, height)];
    // 如果不想调试效果,直接使用这句,画1/4个圆
//    [path2 addArcWithCenter:CGPointMake(0, 6) radius:14 startAngle:M_PI_2 endAngle:0 clockwise:NO];
    // 这是不断调试效果后的结果,画一个二阶贝塞尔曲线
    [path2 addQuadCurveToPoint:CGPointMake(flex, 6) controlPoint:CGPointMake(flex, height)];
    [path2 addLineToPoint:CGPointMake(flex, height)];
    [path2 closePath];

    CAShapeLayer *tipsLayer2 = [CAShapeLayer layer];
    tipsLayer2.path = path2.CGPath;
    tipsLayer2.fillColor = UIColorFromRGB(0xFFEEE8).CGColor;
    [_tipsButton.layer insertSublayer:tipsLayer2 atIndex:0];

最后效果图

image4.png

后面偶然发现,UIBezierPath可以将2个path叠加,优化后的代码

    // 根据内容取得文字宽度,已设置按钮的contentEdgeInserts
    CGFloat width = _tipsButton.intrinsicContentSize.width;
    // 此处要用设置的高度20,而不能取内容高度
    CGFloat height = 20;
    // 左边不规则图形宽度
    CGFloat flex = 12;
    // 将效果拆分,一个是矩形圆角,一个是不规则色块
    UIBezierPath *path1 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(flex, 0, width-flex, height) byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomRight cornerRadii:CGSizeMake(4, 4)];
    
    // 不规则图形
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(0, height)];
    // 如果不想调试效果,直接使用这句,画1/4个圆
//    [path2 addArcWithCenter:CGPointMake(0, 6) radius:14 startAngle:M_PI_2 endAngle:0 clockwise:NO];
    // 这是不断调试效果后的结果,画一个二阶贝塞尔曲线
    [path2 addQuadCurveToPoint:CGPointMake(flex, 6) controlPoint:CGPointMake(flex, height)];
    [path2 addLineToPoint:CGPointMake(flex, height)];
    [path2 closePath];
    
    // 两个path叠加 
    [path1 appendPath:path2];
    
    CAShapeLayer *tipsLayer = [CAShapeLayer layer];
    tipsLayer.path = path1.CGPath;
    tipsLayer.fillColor = UIColorFromRGB(0xFFEEE8).CGColor;
    [_tipsButton.layer insertSublayer:tipsLayer atIndex:0];
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容