Маска Core CGImage не влияет на
То, что я в основном пытаюсь сделать, это иметь текстовую метку "вырезать" текстовое отверстие в представлении. Я пробовал использовать self.mask = uiLabel
, но они отказались правильно позиционировать текст, поэтому я подхожу к нему через Core Graphics.
Здесь код, который не работает (в 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, который не работал. Также, когда я попытался преобразовать CGImage (mask
) в CGColorSpaceCreateDeviceGray()
с помощью .copy(colorSpace:)
, он вернул nil
. Я был на этом в течение двух дней, поэтому любая помощь приветствуется
Ответы
Ответ 1
Если вы хотите, чтобы метка имела полностью прозрачный текст, вы можете использовать режимы наложения вместо масок.
public class KnockoutLabel: UILabel {
public override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()!
context.setBlendMode(.clear)
self.drawText(in: rect)
}
}
Обязательно установите isOpaque
на false
, хотя; по умолчанию представление предполагает, что оно непрозрачно, поскольку вы используете непрозрачный цвет фона.
Ответ 2
Я не уверен, что вам понравится код ниже. Это было сделано с помощью PaintCode. Текст будет всегда в центре закругленного прямоугольника. Надеюсь, это поможет вам.
Код, поместите его внутри 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()
Результаты:
![введите описание изображения здесь]()
![введите описание изображения здесь]()
![введите описание изображения здесь]()