2017-07-26 65 views
14

我基本上試圖做的是在視圖中有一個文本標籤「剪切」文本形狀的洞。我試過使用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()'來修復它。 –

回答

1

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

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

1

我不確定你會喜歡下面的代碼。它是通過使用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