È possibile definire un percorso che è un esagono con angoli arrotondati (che definiscono tale percorso manualmente) e successivamente applicare che la maschera e bordo sottolivello:
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];
Quando il percorso di un poligono regolare con angoli arrotondati potrebbero essere implementate in una categoria in questo modo:
@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
E
@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;
}
che produce qualcosa in questo modo:

O a Swift 3 si potrebbe fare:
Con
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
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
}
}
Per Swift 2 rendition, vedere previous revision of this answer.
C'è un po 'di matematica utili e dettagliate su arrotondare gli angoli di un poligono qui: http://stackoverflow.com/questions/20442203/uibezierpath-triangle-with-rounded-edges –