我正在尝试为我成功的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.