核心图形CGImage面具不影响
问题描述:
我基本上试图做的是在视图中有一个文本标签“剪切”文本形状的洞。我试过使用self.mask = uiLabel
,但那些拒绝正确放置文本,所以我通过核心图形接近这一点。核心图形CGImage面具不影响
这里是不工作的代码(在draw(_ rect: CGRect)
):这是我要敷面膜
let context = (UIGraphicsGetCurrentContext())!
// Set mask background color
context.setFillColor(UIColor.black.cgColor)
context.fill(rect)
context.saveGState()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let attributes = [
NSParagraphStyleAttributeName: paragraphStyle,
NSFontAttributeName: UIFont.systemFont(ofSize: 16, weight: UIFontWeightMedium),
NSForegroundColorAttributeName: UIColor.white
]
let string = NSString(string: "LOGIN")
// This wouldn't vertically align so we calculate the string size and create a new rect in which it is vertically aligned
let size = string.size(attributes: attributes)
let position = CGRect(
x: rect.origin.x,
y: rect.origin.y + (rect.size.height - size.height)/2,
width: rect.size.width,
height: size.height
)
context.translateBy(x: 0, y: rect.size.height)
context.scaleBy(x: 1, y: -1)
string.draw(
in: position,
withAttributes: attributes
)
let mask = (context.makeImage())!
context.restoreGState()
// Redraw with created mask
context.clear(rect)
context.saveGState()
// !!!! Below line is the problem
context.clip(to: rect, mask: mask)
context.restoreGState()
基本上我已经成功地创建了代码来创建一个CGImage
(在mask
变量)到整个图像。
标记的行当替换与context.draw(mask, in: rect)
(查看掩码)正确显示。该面具显示(正确)为:
然而,一旦我尝试将此面膜(使用context.clip(to: rect, mask: mask)
)没有任何反应! 实际结果:
期望的结果是:
但由于某种原因掩模没有被正确地应用。
此代码似乎应该工作,因为我一遍又一遍地阅读文档。我另外试图在一个单独的CGContext中创建了一个不起作用的掩码。当我尝试使用.copy(colorSpace:)
将CGImage(mask
)转换为CGColorSpaceCreateDeviceGray()
时,它返回nil
。我已经在这个为期两天,所以任何帮助表示赞赏
答
如果您希望标签具有完全半透明的文本,您可以使用混合模式,而不是掩码。
public class KnockoutLabel: UILabel {
public override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()!
context.setBlendMode(.clear)
self.drawText(in: rect)
}
}
务必将isOpaque
到false
虽然;默认情况下视图假定它是不透明的,因为你使用了不透明的背景颜色。
答
我不确定你会喜欢下面的代码。它是通过使用PaintCode制作的。文本将始终位于圆角矩形的中心。希望它能帮助你。
代码,将其放在平局(_ RECT:的CGRect):
//// General Declarations
let context = UIGraphicsGetCurrentContext()
//// Color Declarations - just to make a gradient same as your button have
let gradientColor = UIColor(red: 0.220, green: 0.220, blue: 0.223, alpha: 1.000)
let gradientColor2 = UIColor(red: 0.718, green: 0.666, blue: 0.681, alpha: 1.000)
let gradientColor3 = UIColor(red: 0.401, green: 0.365, blue: 0.365, alpha: 1.000)
//// Gradient Declarations
let gradient = CGGradient(colorsSpace: nil, colors: [gradientColor.cgColor, gradientColor3.cgColor, gradientColor2.cgColor] as CFArray, locations: [0, 0.55, 1])!
//// Subframes
let group: CGRect = CGRect(x: rect.minX, y: rect.minY, width: rect.width, height: rect.height)
//// Group
context.saveGState()
context.beginTransparencyLayer(auxiliaryInfo: nil)
//// Rectangle Drawing
let rectanglePath = UIBezierPath(roundedRect: group, cornerRadius: 5)
context.saveGState()
rectanglePath.addClip()
let rectangleRotatedPath = UIBezierPath()
rectangleRotatedPath.append(rectanglePath)
var rectangleTransform = CGAffineTransform(rotationAngle: -99 * -CGFloat.pi/180)
rectangleRotatedPath.apply(rectangleTransform)
let rectangleBounds = rectangleRotatedPath.cgPath.boundingBoxOfPath
rectangleTransform = rectangleTransform.inverted()
context.drawLinearGradient(gradient,
start: CGPoint(x: rectangleBounds.minX, y: rectangleBounds.midY).applying(rectangleTransform),
end: CGPoint(x: rectangleBounds.maxX, y: rectangleBounds.midY).applying(rectangleTransform),
options: [])
context.restoreGState()
//// Text Drawing
context.saveGState()
context.setBlendMode(.destinationOut)
let textRect = group
let textTextContent = "LOGIN"
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = .center
let textFontAttributes = [
NSFontAttributeName: UIFont.systemFont(ofSize: 16, weight: UIFontWeightBold),
NSForegroundColorAttributeName: UIColor.black,
NSParagraphStyleAttributeName: textStyle,
]
let textTextHeight: CGFloat = textTextContent.boundingRect(with: CGSize(width: textRect.width, height: CGFloat.infinity), options: .usesLineFragmentOrigin, attributes: textFontAttributes, context: nil).height
context.saveGState()
context.clip(to: textRect)
textTextContent.draw(in: CGRect(x: textRect.minX, y: textRect.minY + (textRect.height - textTextHeight)/2, width: textRect.width, height: textTextHeight), withAttributes: textFontAttributes)
context.restoreGState()
context.restoreGState()
context.endTransparencyLayer()
context.restoreGState()
结果:
我也有类似的问题,一旦,但我的设置略有不同:'UIControl' c带有UILabel子视图的ustom子类。 –
在我的情况下,在渲染mas之前,在标签子视图上调用'setNeedsDisplay()'来修复它。 –