简体   繁体   English

核心图形CGImage掩码不会影响

[英]Core Graphics CGImage mask not affecting

What I'm essentially trying to do is have a text label 'cut' a text-shaped hole through the view. 我实际上要做的是在视图中有一个文本标签“切割”一个文本形状的孔。 I've tried using self.mask = uiLabel but those refused to position the text correctly so I'm approaching this through Core Graphics. 我尝试过使用self.mask = uiLabel但那些人拒绝正确定位文本所以我通过Core Graphics接近这个。

Here's the code that isn't working (in the draw(_ rect: CGRect) ): 这是不起作用的代码(在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()

Essentially I've successfully created the code to create a CGImage (the mask variable) which is the mask I want to apply to the whole image. 基本上我已经成功创建了代码来创建CGImagemask变量),这是我想要应用于整个图像的掩码。

The marked line when replaced with context.draw(mask, in: rect) (to view the mask) correctly displays. 替换context.draw(mask, in: rect) (以查看掩码)时标记的行正确显示。 The mask shows (correctly) as: 掩码显示(正确)为:

在此输入图像描述 :

However once I try to apply this mask (using the context.clip(to: rect, mask: mask) ) nothing happens!. 然而,一旦我尝试应用这个掩码(使用context.clip(to: rect, mask: mask) )没有任何反应! Actual result: 实际结果:

没有变化

Desired result is: 期望的结果是:

期望的结果

but for some reason the mask is not being correctly applied. 但由于某种原因,掩码未正确应用。


This code seems like it should work as I've read the docs over and over again. 这段代码似乎应该可以正常工作,因为我一遍又一遍地阅读文档。 I've additionally tried to create the mask in a separate CGContext which didn't work. 我还试图在一个单独的CGContext中创建掩码,但它不起作用。 Also when I tried to convert the CGImage ( mask ) to CGColorSpaceCreateDeviceGray() using .copy(colorSpace:) , it returned nil . 此外,当我尝试使用.copy(colorSpace:)将CGImage( mask )转换为CGColorSpaceCreateDeviceGray() ,它返回nil I've been at this for two days so any help is appreciated 我已经在这两天了,所以任何帮助都表示赞赏

If you want the label to have fully translucent text, you can use blend modes instead of masks. 如果您希望标签具有完全半透明的文本,则可以使用混合模式而不是蒙版。

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

        self.drawText(in: rect)
    }
}

Make sure to set isOpaque to false though; 确保将isOpaque设置为false ; by default the view assumes it is opaque, since you use an opaque background color. 默认情况下,视图假定它是不透明的,因为您使用不透明的背景颜色。

I'm not actually sure that you will enjoy the code below. 我真的不确定你会喜欢下面的代码。 It was made by using the PaintCode. 它是使用PaintCode制作的。 Text will be always at the center of rounded rectangle. 文本将始终位于圆角矩形的中心。 Hope it will help you. 希望它会对你有所帮助。

Code, put it inside draw(_ rect: CGRect): 代码,把它放在draw(_ 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()

Results: 结果:

在此输入图像描述

在此输入图像描述

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM