iOS图形处理相关iOS头条干货iOS备忘录

iOS/OC: Quartz2D画圆角矩形时的线宽不一致问题-

2016-06-27  本文已影响604人  疯狂的向日葵

版权声明:本文为博主原创文章,未经博主允许不得转载。

圆角矩形一般直接AddArc...或者用BezierPath,

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
+(instancetype)ImageFromFrame:(CGSize)size
                  BorderColor:(UIColor *)color
                 BorderRadius:(CGFloat)radius
                  BorderWidth:(CGFloat)width
{
    CGFloat x = size.width;
    CGFloat y = size.height;
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetRGBFillColor (context,  1.0, 1.0, 1.0, 1.0);//设置填充颜色(白色)
    CGContextSetLineWidth(context, width);//线的宽度
    CGContextSetStrokeColorWithColor(context, color.CGColor);//线框颜色
//方法1
    //    CGPathRef clippath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0,0, x, y)cornerRadius:radius].CGPath;
    //    CGContextAddPath(context, clippath);
//方法2
    CGContextMoveToPoint(context, x, y-radius);  // 开始坐标右边开始
    CGContextAddArcToPoint(context, x, y, x-radius, y, radius);  // 右下角角度
    CGContextAddLineToPoint(context, radius, y);
    CGContextAddArcToPoint(context, 0, y, 0, y-radius, radius); // 左下角角度
    CGContextAddLineToPoint(context, 0, radius);
    CGContextAddArcToPoint(context, 0, 0, radius, 0, radius); // 左上角
    CGContextAddLineToPoint(context, x-radius, 0);
    CGContextAddArcToPoint(context, x, 0, x, radius, radius); // 右上角
    CGContextClosePath(context);

    CGContextDrawPath(context, kCGPathFillStroke); 
    UIImage *newImage=UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

这个方法看上去没什么问题,的确是按背景大小沿着路径画的,但是调试一下就会发现,当背景的clipsToBounds = YES时,画出来的圆角矩形圆角处的线宽和直线的线宽是不一致的,效果非常诡异.感觉边缘都被截去了,也就是说 画出的圆角矩形超出了背景大小

9E7D47FF-40E5-4465-ACD7-0BC5F6983F4B.png

找了好久,后发现一篇有用的博文

跟Quartz2D的绘制时的抗锯齿机制有关
http://my.oschina.net/lych0317/blog/126215
具体原理看博文,不过里面的代码也是有问题的.

正确完美的解决方案如下:

路径及半径要往里扣除线宽的一半 !!!!

UIImage的分类

#import <UIKit/UIKit.h>
@interface UIImage (JLImage)
/**
 绘制圆角矩形
 
 @param size 画布大小
 @param borderColor 边缘颜色
 @param borderRadius 圆角半径
 @param borderWidth 线宽
 @param margin 上下左右间距
 */
+ (instancetype)roundRectImageWithFrame:(CGSize)size
                            borderColor:(UIColor *)borderColor
                           borderRadius:(CGFloat)borderRadius
                            borderWidth:(CGFloat)borderWidth
                                 margin:(CGFloat)margin;
@end
#import "UIImage+JLImage.h"
@implementation UIImage (JLImage)
+ (instancetype)roundRectImageWithFrame:(CGSize)size
                            borderColor:(UIColor *)borderColor
                           borderRadius:(CGFloat)borderRadius
                            borderWidth:(CGFloat)borderWidth
                                 margin:(CGFloat)margin
{
       CGFloat x = size.width;
    CGFloat y = size.height;
    CGFloat radius = borderRadius - margin;
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetRGBFillColor (context,  1.0, 1.0, 1.0, 1.0);//设置填充颜色(白色)
    CGContextSetLineWidth(context, borderWidth);//线的宽度
    CGContextSetStrokeColorWithColor(context, borderColor.CGColor);//线框颜色
    //绘制path 方法1
    CGPathRef clippath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(borderWidth/2 +margin,borderWidth/2 +margin, x - borderWidth - margin*2, y - borderWidth - margin*2)cornerRadius:radius].CGPath;
    CGContextAddPath(context, clippath);
    //绘制path 方法2
//    CGContextMoveToPoint(context, x-borderWidth/2 -margin, y-radius - margin);  // 开始坐标右边开始
//    CGContextAddArcToPoint(context, x-borderWidth/2 -margin, y-borderWidth/2 - margin, x-radius -margin, y-borderWidth/2-margin, radius - borderWidth/2);  // 右下角角度
//    CGContextAddLineToPoint(context, radius+margin, y-borderWidth/2-margin);
//    CGContextAddArcToPoint(context,  borderWidth/2+margin, y-borderWidth/2-margin, borderWidth/2+margin, y-radius-margin, radius-borderWidth/2); // 左下角角度
//    CGContextAddLineToPoint(context, borderWidth/2 +margin, radius+margin);
//    CGContextAddArcToPoint(context, borderWidth/2+margin, borderWidth/2+margin, radius+margin, borderWidth/2+margin, radius-borderWidth/2); // 左上角
//    CGContextAddLineToPoint(context, x-radius-borderWidth/2-margin, borderWidth/2 +margin);
//    CGContextAddArcToPoint(context, x-borderWidth/2- margin, borderWidth/2 +margin, x-borderWidth/2 - margin, radius +margin, radius-borderWidth/2); // 右上角
//    CGContextClosePath(context);
    //填充
    CGContextDrawPath(context, kCGPathFillStroke); 
    UIImage *newImage=UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}
@end

方法1和方法2效果是一样的

A2AC47A0-C9B5-48A8-86B9-8C498DC1C2C1.png
上一篇下一篇

猜你喜欢

热点阅读