Как нарисовать UILabel с другим режимом наложения в Draw(_ rect: CGRect) в Swift

Итак, у меня есть UILabel который рисуется поверх градиентного изображения (то есть UIImageView). Это выглядит примерно так:

введите описание изображения здесь

Я пытаюсь изменить blendMode графического контекста в UILabel"s draw(_ rect: CGRect) функция так, что он рисует метку, но смешивается с фоном с softLight Режим наложения.

Вот как я хочу, чтобы это выглядело так:

введите описание изображения здесь

Вот код, который я имею в draw(_ rect: CGRect) функция:

override func draw(_ rect: CGRect) {
    // Drawing code
     if let context = UIGraphicsGetCurrentContext() {
        context.setBlendMode(.softLight)
        self.textColor.set()
        self.drawText(in: rect)
   }
 }

Этот код просто отображает верхнюю картинку, а не смешанную версию. Это не все, что я пробовал, я пробовал так много других вещей, но я просто не понимаю, CGContextи draw функция в частности.

Большинство ответов на SO либо в старом target-c и устарели / сломаны, либо быстры и слишком сложны (например, используйте Metal). Я просто хочу нарисовать текст в моем контексте и установить режим смешивания контекста на мягкий свет. Там должен быть легкий путь!

Любая помощь о том, как это исправить, будет принята с благодарностью. Спасибо!

2 ответа

Решение

Вы не можете смешивать взгляды таким образом; у них есть отдельные иерархии слоев, которые разрешаются независимо. Переместите градиент и текст на CALayer объекты и смешать их (или нарисовать их вручную в том же виде). Например:

class MyView: UIView {
    let gradientLayer: CAGradientLayer = {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [UIColor.red.cgColor,
                                UIColor.blue.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        return gradientLayer
    }()

    let textLayer: CATextLayer = {
        let textLayer = CATextLayer()
        let astring = NSAttributedString(string: "Text Example",
                                         attributes: [.font: UIFont(name: "MarkerFelt-Wide", size: 60)!])
        textLayer.string = astring
        textLayer.alignmentMode = kCAAlignmentCenter
        textLayer.bounds = astring.boundingRect(with: CGSize(width: .max, height: .max),
                                                options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
        return textLayer
    }()

    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            gradientLayer.bounds = bounds
            gradientLayer.render(in: context)

            context.saveGState()
            context.setBlendMode(.softLight)

            context.translateBy(x: center.x - textLayer.bounds.width / 2,
                                y: center.y - textLayer.bounds.height / 2)

            textLayer.position = center
            textLayer.render(in: context)
            context.restoreGState()
        }
    }
}

Поэтому, если ваш текст действительно является меткой, вы можете попробовать изменить прозрачность, как для обычных меток. Я предполагаю, что вы знакомы с настройкой альфа-метки для ярлыка. Ниже приведен один пример установки альфа-метки для ярлыка:

label.textColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.25)

Пожалуйста, дайте мне подсказку, если это не лейбл - тогда это должно быть более сложным.

Другие вопросы по тегам