核心图形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)(查看掩码)正确显示。该面具显示(正确)为:

enter image description here

然而,一旦我尝试将此面膜(使用context.clip(to: rect, mask: mask))没有任何反应! 实际结果:

Nothing changing

期望的结果是

Desired result

但由于某种原因掩模没有被正确地应用。


此代码似乎应该工作,因为我一遍又一遍地阅读文档。我另外试图在一个单独的CGContext中创建了一个不起作用的掩码。当我尝试使用.copy(colorSpace:)将CGImage(mask)转换为CGColorSpaceCreateDeviceGray()时,它返回nil。我已经在这个为期两天,所以任何帮助表示赞赏

+0

我也有类似的问题,一旦,但我的设置略有不同:'UIControl' c带有UILabel子视图的ustom子类。 –

+0

在我的情况下,在渲染mas之前,在标签子视图上调用'setNeedsDisplay()'来修复它。 –

如果您希望标签具有完全半透明的文本,您可以使用混合模式,而不是掩码。

public class KnockoutLabel: UILabel { 
    public override func draw(_ rect: CGRect) { 
     let context = UIGraphicsGetCurrentContext()! 
     context.setBlendMode(.clear) 

     self.drawText(in: rect) 
    } 
} 

务必将isOpaquefalse虽然;默认情况下视图假定它是不透明的,因为你使用了不透明的背景颜色。

+0

不知道它是什么,但这似乎与'UIVisualEffectView'不太匹配。其他混合模式也不会 – Downgoat

+0

@Downgoat你究竟想要达到什么样的目标?问题是什么? –

+0

问题与问题相同,在设置混合模式时,按钮看起来没有变化。这应该只是一个UI效果 – Downgoat

我不确定你会喜欢下面的代码。它是通过使用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() 

结果:

enter image description here

enter image description here

enter image description here