ios – 如何用Hexagon面具圆角UIImage的角落

前端之家收集整理的这篇文章主要介绍了ios – 如何用Hexagon面具圆角UIImage的角落前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试为我成功的UI Image添加一个六边形面具.但是我无法绕六边形面具的两侧.我想加上cell.profilePic.layer.cornerRadius = 10;会做的伎俩,但它没有.

这是我的代码

CGRect rect = cell.profilePic.frame;

CAShapeLayer *hexagonMask = [CAShapeLayer layer];
CAShapeLayer *hexagonBorder = [CAShapeLayer layer];
hexagonBorder.frame = cell.profilePic.layer.bounds;
UIBezierPath *hexagonPath = [UIBezierPath bezierPath];
CGFloat sideWidth = 2 * ( 0.5 * rect.size.width / 2 );
CGFloat lcolumn = ( rect.size.width - sideWidth ) / 2;
CGFloat rcolumn = rect.size.width - lcolumn;
CGFloat height = 0.866025 * rect.size.height;
CGFloat y = (rect.size.height - height) / 2;
CGFloat by = rect.size.height - y;
CGFloat midy = rect.size.height / 2;
CGFloat rightmost = rect.size.width;
[hexagonPath moveToPoint:CGPointMake(lcolumn,y)];
[hexagonPath addLineToPoint:CGPointMake(rcolumn,y)];
[hexagonPath addLineToPoint:CGPointMake(rightmost,midy)];
[hexagonPath addLineToPoint:CGPointMake(rcolumn,by)];
[hexagonPath addLineToPoint:CGPointMake(lcolumn,by)];
[hexagonPath addLineToPoint:CGPointMake(0,midy)];
[hexagonPath addLineToPoint:CGPointMake(lcolumn,y)];

hexagonMask.path = hexagonPath.CGPath;
hexagonBorder.path = hexagonPath.CGPath;
hexagonBorder.fillColor = [UIColor clearColor].CGColor;
hexagonBorder.strokeColor = [UIColor blackColor].CGColor;
hexagonBorder.lineWidth = 5;
cell.profilePic.layer.mask = hexagonMask;
cell.profilePic.layer.cornerRadius = 10;
cell.profilePic.layer.masksToBounds = YES;
[cell.profilePic.layer addSublayer:hexagonBorder];

有任何想法吗?

谢谢

解决方法

您可以定义一个带圆角的六边形路径(手动定义该路径),然后将其应用为蒙版和边框子图层:
CGFloat lineWidth    = 5.0;
UIBezierPath *path   = [UIBezierPath polygonInRect:self.imageView.bounds
                                             sides:6
                                         lineWidth:lineWidth
                                      cornerRadius:30];

// mask for the image view

CAShapeLayer *mask   = [CAShapeLayer layer];
mask.path            = path.CGPath;
mask.lineWidth       = lineWidth;
mask.strokeColor     = [UIColor clearColor].CGColor;
mask.fillColor       = [UIColor whiteColor].CGColor;
self.imageView.layer.mask = mask;

// if you also want a border,add that as a separate layer

CAShapeLayer *border = [CAShapeLayer layer];
border.path          = path.CGPath;
border.lineWidth     = lineWidth;
border.strokeColor   = [UIColor blackColor].CGColor;
border.fillColor     = [UIColor clearColor].CGColor;
[self.imageView.layer addSublayer:border];

具有圆角的正多边形的路径可能在类似的类别中实现:

@interface UIBezierPath (Polygon)

/** Create UIBezierPath for regular polygon with rounded corners
 *
 * @param rect          The CGRect of the square in which the path should be created.
 * @param sides         How many sides to the polygon (e.g. 6=hexagon; 8=octagon,etc.).
 * @param lineWidth     The width of the stroke around the polygon. The polygon will be inset such that the stroke stays within the above square.
 * @param cornerRadius  The radius to be applied when rounding the corners.
 *
 * @return              UIBezierPath of the resulting rounded polygon path.
 */

+ (instancetype)polygonInRect:(CGRect)rect sides:(NSInteger)sides lineWidth:(CGFloat)lineWidth cornerRadius:(CGFloat)cornerRadius;

@end

@implementation UIBezierPath (Polygon)

+ (instancetype)polygonInRect:(CGRect)rect sides:(NSInteger)sides lineWidth:(CGFloat)lineWidth cornerRadius:(CGFloat)cornerRadius {
    UIBezierPath *path  = [UIBezierPath bezierPath];

    CGFloat theta       = 2.0 * M_PI / sides;                           // how much to turn at every corner
    CGFloat offset      = cornerRadius * tanf(theta / 2.0);             // offset from which to start rounding corners
    CGFloat squareWidth = MIN(rect.size.width,rect.size.height);   // width of the square

    // calculate the length of the sides of the polygon

    CGFloat length      = squareWidth - lineWidth;
    if (sides % 4 != 0) {                                               // if not dealing with polygon which will be square with all sides ...
        length = length * cosf(theta / 2.0) + offset/2.0;               // ... offset it inside a circle inside the square
    }
    CGFloat sideLength = length * tanf(theta / 2.0);

    // start drawing at `point` in lower right corner

    CGPoint point = CGPointMake(rect.origin.x + rect.size.width / 2.0 + sideLength / 2.0 - offset,rect.origin.y + rect.size.height / 2.0 + length / 2.0);
    CGFloat angle = M_PI;
    [path moveToPoint:point];

    // draw the sides and rounded corners of the polygon

    for (NSInteger side = 0; side < sides; side++) {
        point = CGPointMake(point.x + (sideLength - offset * 2.0) * cosf(angle),point.y + (sideLength - offset * 2.0) * sinf(angle));
        [path addLineToPoint:point];

        CGPoint center = CGPointMake(point.x + cornerRadius * cosf(angle + M_PI_2),point.y + cornerRadius * sinf(angle + M_PI_2));
        [path addArcWithCenter:center radius:cornerRadius startAngle:angle - M_PI_2 endAngle:angle + theta - M_PI_2 clockwise:YES];

        point = path.currentPoint; // we don't have to calculate where the arc ended ... UIBezierPath did that for us
        angle += theta;
    }

    [path closePath];

    path.lineWidth = lineWidth;           // in case we're going to use CoreGraphics to stroke path,rather than CAShapeLayer
    path.lineJoinStyle = kCGLineJoinRound;

    return path;
}

产生这样的结果:

或者在Swift 3中你可以这样做:

let lineWidth: CGFloat = 5
let path = UIBezierPath(polygonIn: imageView.bounds,sides: 6,lineWidth: lineWidth,cornerRadius: 30)

let mask = CAShapeLayer()
mask.path            = path.cgPath
mask.lineWidth       = lineWidth
mask.strokeColor     = UIColor.clear.cgColor
mask.fillColor       = UIColor.white.cgColor
imageView.layer.mask = mask

let border = CAShapeLayer()
border.path          = path.cgPath
border.lineWidth     = lineWidth
border.strokeColor   = UIColor.black.cgColor
border.fillColor     = UIColor.clear.cgColor
imageView.layer.addSublayer(border)

extension UIBezierPath {

    /// Create UIBezierPath for regular polygon with rounded corners
    ///
    /// - parameter rect:            The CGRect of the square in which the path should be created.
    /// - parameter sides:           How many sides to the polygon (e.g. 6=hexagon; 8=octagon,etc.).
    /// - parameter lineWidth:       The width of the stroke around the polygon. The polygon will be inset such that the stroke stays within the above square. Default value 1.
    /// - parameter cornerRadius:    The radius to be applied when rounding the corners. Default value 0.

    convenience init(polygonIn rect: CGRect,sides: Int,lineWidth: CGFloat = 1,cornerRadius: CGFloat = 0) {
        self.init()

        let theta = 2 * CGFloat.pi / CGFloat(sides)                 // how much to turn at every corner
        let offset = cornerRadius * tan(theta / 2)                  // offset from which to start rounding corners
        let squareWidth = min(rect.size.width,rect.size.height)    // width of the square

        // calculate the length of the sides of the polygon

        var length = squareWidth - lineWidth
        if sides % 4 != 0 {                                         // if not dealing with polygon which will be square with all sides ...
            length = length * cos(theta / 2) + offset / 2           // ... offset it inside a circle inside the square
        }
        let sideLength = length * tan(theta / 2)

        // if you'd like to start rotated 90 degrees,use these lines instead of the following two:
        //
        // var point = CGPoint(x: rect.midX - length / 2,y: rect.midY + sideLength / 2 - offset)
        // var angle = -CGFloat.pi / 2.0

        // if you'd like to start rotated 180 degrees,use these lines instead of the following two:
        //
        // var point = CGPoint(x: rect.midX - sideLength / 2 + offset,y: rect.midY - length / 2)
        // var angle = CGFloat(0)

        var point = CGPoint(x: rect.midX + sideLength / 2 - offset,y: rect.midY + length / 2)
        var angle = CGFloat.pi

        move(to: point)

        // draw the sides and rounded corners of the polygon

        for _ in 0 ..< sides {
            point = CGPoint(x: point.x + (sideLength - offset * 2) * cos(angle),y: point.y + (sideLength - offset * 2) * sin(angle))
            addLine(to: point)

            let center = CGPoint(x: point.x + cornerRadius * cos(angle + .pi / 2),y: point.y + cornerRadius * sin(angle + .pi / 2))
            addArc(withCenter: center,radius: cornerRadius,startAngle: angle - .pi / 2,endAngle: angle + theta - .pi / 2,clockwise: true)

            point = currentPoint
            angle += theta
        }

        close()

        self.lineWidth = lineWidth           // in case we're going to use CoreGraphics to stroke path,rather than CAShapeLayer
        lineJoinStyle = .round
    }

}

对于Swift 2的演绎,请参阅previous revision of this answer.

猜你在找的iOS相关文章