1. 填充颜色时设置混合模式
func radiusMaskImage() -> UIImage? {
let size = CGSize.init(width: 100, height: 100)
let cornerRadius: CGFloat = 50
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
UIColor.red.setFill()
UIRectFill(CGRect.init(origin: CGPoint.zero, size: size))
let path = UIBezierPath.init(roundedRect: CGRect.init(origin: CGPoint.zero, size: size), cornerRadius: cornerRadius)
// 设置BlendMode为clear
path.fill(with: CGBlendMode.clear, alpha: 1)
var image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let inset = cornerRadius + 1
image = image?.resizableImage(withCapInsets: UIEdgeInsets.init(top: inset, left: inset, bottom: inset, right: inset), resizingMode: UIImageResizingMode.stretch)
return image
}
CGBlendMode: 绘制时使用的混合模式,设置为clear,在绘制时显示为透明
2. 设置fillRule
填充区域的计算规则有even-odd和non-zero。
even-odd:奇偶规则,从指定区域的一点绘制到路径外的任意一点,交点个数为偶数则认为这点在范围内,并填充相应的区域。为奇数则认为这点不在范围内,所在区域不会被填充。
non-zero: 非零规则,从指定区域的一点绘制到路径外的任意一点,与从左到右的路径相交,数值+1,与从右到左的的路径相交,数值-1,如果最后的总值非零认为这点在范围内,并填充相应的区域。为零则认为这点不在范围内,所在区域不会被填充。
在苹果官方文档有说明:https://developer.apple.com/documentation/uikit/uibezierpath/1624360-usesevenoddfillrule
一. 设置fillRule 为even-odd rule
func radiusMaskImage() -> UIImage? {
let size = CGSize.init(width: 100, height: 100)
let cornerRadius: CGFloat = 50
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
UIColor.red.setFill()
let path = UIBezierPath.init(roundedRect: CGRect.init(origin: CGPoint.zero, size: size), cornerRadius: cornerRadius)
path.append(UIBezierPath.init(rect: CGRect.init(origin: CGPoint.zero, size: size)))
// 设置填充规则为even-odd
path.usesEvenOddFillRule = true
path.fill()
var image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let inset = cornerRadius + 1
image = image?.resizableImage(withCapInsets: UIEdgeInsets.init(top: inset, left: inset, bottom: inset, right: inset), resizingMode: UIImageResizingMode.stretch)
return image
}
二. 使用non-zero rule
func radiusMaskImage() -> UIImage? {
let size = CGSize.init(width: 100, height: 100)
let cornerRadius: CGFloat = 50
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
UIColor.red.setFill()
let path = UIBezierPath.init(rect: CGRect.init(origin: CGPoint.zero, size: size))
// 添加一个逆时针的圆
path.append(UIBezierPath.init(arcCenter: CGPoint.init(x: size.width / 2, y: size.height / 2), radius: cornerRadius, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: false))
path.fill()
var image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let inset = cornerRadius + 1
image = image?.resizableImage(withCapInsets: UIEdgeInsets.init(top: inset, left: inset, bottom: inset, right: inset), resizingMode: UIImageResizingMode.stretch)
return image
}
最后上图: