我需要像六角形一样给出imageView
的界限。我在Stack Overflow中搜索并获取代码,但它并不完全满足需要。
答案 0 :(得分:2)
好的,这是一个如何做的例子。
首先,在UIBezierPath
上创建一个类别:
<强>目标C 强>:
.h文件:
@import UIKit.UIBezierPath;
@interface UIBezierPath (Additions)
+ (UIBezierPath * _Nullable)bezierPathWithSquare:(CGRect)square numberOfSides:(NSUInteger)numberOfSides cornerRadius:(CGFloat)cornerRadius;
@end
.m文件:
#import "UIBezierPath+Additions.h"
@implementation UIBezierPath (Additions)
+ (UIBezierPath *)bezierPathWithSquare:(CGRect)square numberOfSides:(NSUInteger)numberOfSides cornerRadius:(CGFloat)cornerRadius
{
if ( CGRectGetWidth(square) != CGRectGetHeight(square) )
{
return nil;
}
CGFloat squareWidth = CGRectGetWidth(square);
if ( numberOfSides == 0 || cornerRadius < 0.0 || 2.0 * cornerRadius > squareWidth || CGRectIsInfinite(square) || CGRectIsEmpty(square) || CGRectIsNull(square) )
{
return nil;
}
UIBezierPath *path = [UIBezierPath new];
CGFloat theta = 2.0 * M_PI / numberOfSides;
CGFloat offset = cornerRadius * tan(0.5 * theta);
CGFloat length = squareWidth - path.lineWidth;
if ( numberOfSides % 4 != 0 )
{
length = length * cos(0.5 * theta);
}
CGFloat sideLength = length * tan(0.5 * theta);
CGFloat p1 = squareWidth / 2.0 + sideLength / 2.0 - offset;
CGFloat p2 = squareWidth - (squareWidth - length) / 2.0;
CGPoint point = CGPointMake(p1, p2);
CGFloat angle = M_PI;
[path moveToPoint:point];
for ( NSUInteger i = 0; i < numberOfSides; i++ )
{
CGFloat x1 = point.x + ( sideLength - offset * 2.0 ) * cos(angle);
CGFloat y1 = point.y + ( sideLength - offset * 2.0 ) * sin(angle);
point = CGPointMake(x1, y1);
[path addLineToPoint:point];
CGFloat centerX = point.x + cornerRadius * cos(angle + M_PI_2);
CGFloat centerY = point.y + cornerRadius * sin(angle + M_PI_2);
CGPoint center = CGPointMake(centerX, centerY);
CGFloat radius = cornerRadius;
CGFloat startAngle = angle - M_PI_2;
CGFloat endAngle = angle + theta - M_PI_2;
[path addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
point = path.currentPoint;
angle += theta;
}
[path closePath];
return path;
}
@end
然后,您的视图控制器的实现将如下所示:
#import "ViewController.h"
#import "UIBezierPath+Additions.h"
@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupImageViewHexagonMask];
}
- (void)setupImageViewHexagonMask
{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithSquare:self.imageView.bounds numberOfSides:6 cornerRadius:20.0];
CAShapeLayer *maskingLayer = [CAShapeLayer layer];
maskingLayer.path = maskPath.CGPath;
self.imageView.layer.mask = maskingLayer;
}
@end
Swift 2 :
在UIBezierPath
import UIKit
/** Additions Extends UIBezierPath
*/
extension UIBezierPath {
convenience init?(square: CGRect, numberOfSides: UInt, cornerRadius: CGFloat) {
guard CGRectGetWidth(square) == CGRectGetHeight(square) else {
return nil
}
let squareWidth = CGRectGetWidth(square)
guard numberOfSides > 0 && cornerRadius >= 0.0 && 2.0 * cornerRadius < squareWidth && !CGRectIsInfinite(square) && !CGRectIsEmpty(square) && !CGRectIsNull(square) else {
return nil
}
self.init()
// how much to turn at every corner
let theta = CGFloat(2.0 * M_PI) / CGFloat(numberOfSides)
// offset from which to start rounding corners
let offset: CGFloat = cornerRadius * CGFloat(tan( theta / 2.0 ))
var length = squareWidth - lineWidth
if( numberOfSides % 4 != 0){
length = length * cos(theta / 2.0)
}
let sideLength = length * CGFloat(tan(theta / 2.0))
// start drawing ap 'point' in lower right corner
let p1 = squareWidth / 2.0 + sideLength / 2.0 - offset
let p2 = squareWidth - ((squareWidth - length) / 2.0)
var point = CGPointMake(CGFloat(p1), CGFloat(p2))
var angle = CGFloat(M_PI)
moveToPoint(point)
// draw the sides around rounded corners of the polygon
for ( var i: UInt = 0; i < numberOfSides; i++){
let x1 = CGFloat(point.x) + ((sideLength - offset * 2.0) * CGFloat(cos(angle)))
let y1 = CGFloat(point.y) + ((sideLength - offset * 2.0) * CGFloat(sin(angle)))
point = CGPointMake(CGFloat(x1), CGFloat(y1))
addLineToPoint(point)
let centerX = point.x + cornerRadius * CGFloat(cos(angle + CGFloat(M_PI_2)))
let centerY = point.y + cornerRadius * CGFloat(sin(angle + CGFloat(M_PI_2)))
let center = CGPointMake(CGFloat(centerX), CGFloat(centerY))
let radius:CGFloat = CGFloat(cornerRadius)
let startAngle = CGFloat(angle) - CGFloat(M_PI_2)
let endAngle = CGFloat(angle) + CGFloat(theta) - CGFloat(M_PI_2)
addArcWithCenter(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
point = currentPoint
angle += theta
}
closePath()
}
}
示例视图控制器的实现:
import UIKit
class ViewController: UIViewController {
@IBOutlet private weak var imageView: UIImageView!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
applyHexagonMask()
}
private func applyHexagonMask() {
let maskPath = UIBezierPath(square: imageView.bounds, numberOfSides: 6, cornerRadius: 10.0)
let maskingLayer = CAShapeLayer()
maskingLayer.path = maskPath?.CGPath
imageView.layer.mask = maskingLayer
}
}
Swift 4 :
import UIKit
extension UIBezierPath {
convenience init?(square: CGRect, numberOfSides: UInt, cornerRadius: CGFloat) {
guard square.width == square.height else { return nil }
let squareWidth = square.width
guard numberOfSides > 0 && cornerRadius >= 0.0 && 2.0 * cornerRadius < squareWidth && !square.isInfinite && !square.isEmpty && !square.isNull else {
return nil
}
self.init()
// how much to turn at every corner
let theta = 2.0 * .pi / CGFloat(numberOfSides)
let halfTheta = 0.5 * theta
// offset from which to start rounding corners
let offset: CGFloat = cornerRadius * CGFloat(tan(halfTheta))
var length = squareWidth - self.lineWidth
if numberOfSides % 4 > 0 {
length = length * cos(halfTheta)
}
let sideLength = length * CGFloat(tan(halfTheta))
// start drawing at 'point' in lower right corner
let p1 = 0.5 * (squareWidth + sideLength) - offset
let p2 = squareWidth - 0.5 * (squareWidth - length)
var point = CGPoint(x: p1, y: p2)
var angle = CGFloat.pi
self.move(to: point)
// draw the sides around rounded corners of the polygon
for _ in 0..<numberOfSides {
let x1 = CGFloat(point.x) + ((sideLength - offset * 2.0) * CGFloat(cos(angle)))
let y1 = CGFloat(point.y) + ((sideLength - offset * 2.0) * CGFloat(sin(angle)))
point = CGPoint(x: x1, y: y1)
self.addLine(to: point)
let centerX = point.x + cornerRadius * CGFloat(cos(angle + 0.5 * .pi))
let centerY = point.y + cornerRadius * CGFloat(sin(angle + 0.5 * .pi))
let center = CGPoint(x: centerX, y: centerY)
let startAngle = CGFloat(angle) - 0.5 * .pi
let endAngle = CGFloat(angle) + CGFloat(theta) - 0.5 * .pi
self.addArc(withCenter: center, radius: cornerRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
point = self.currentPoint
angle += theta
}
self.close()
}
}
示例视图控制器的实现:
class ViewController: UIViewController {
@IBOutlet private weak var imageView: UIImageView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
applyHexagonMask()
}
private func applyHexagonMask() {
let maskPath = UIBezierPath(square: imageView.bounds, numberOfSides: 6, cornerRadius: 10.0)
let maskingLayer = CAShapeLayer()
maskingLayer.path = maskPath?.cgPath
imageView.layer.mask = maskingLayer
}
}
游乐场的结果:
享受。
答案 1 :(得分:0)
以下代码适用于我:
super()