Отрывистый градиент на границе UIButton - PullRequest
0 голосов
/ 16 апреля 2019

Мне нужно создать закругленную UIButton с градиентом на границе. Что я упустил в коде Core Graphics?

Я создал CAGradientLayer с маской.

        layer.cornerRadius = 43
        let gradient = CAGradientLayer()
        gradient.frame = bounds
        gradient.colors = [UIColor(red: 0.99, green: 0.89, blue: 0.54, alpha: 1).cgColor, UIColor(red: 0.95, green: 0.51, blue: 0.51, alpha: 1).cgColor]
        gradient.locations = [0, 1]
        gradient.startPoint = CGPoint(x: 1.83, y: -0.68)
        gradient.endPoint = CGPoint(x: 0.13, y: 0.82)
        gradient.cornerRadius = 43

        let shape = CAShapeLayer()
        shape.lineWidth = 6
        shape.path = UIBezierPath(roundedRect: gradient.frame, cornerRadius: 43).cgPath
        shape.strokeColor = UIColor.black.cgColor
        shape.fillColor = UIColor.clear.cgColor
        gradient.mask = shape

        layer.addSublayer(gradient)
        setTitleColor(.red, for: .normal)
        titleLabel?.font = Theme.shared.font.bold(ofSize: 25.0)
        clipsToBounds = true

Я ожидаю не резкий градиент, равномерно обрезанный маской.

enter image description here

1 Ответ

0 голосов
/ 16 апреля 2019

Первая проблема заключается в том, что граница пути центрирована по краю рамки, поэтому вам нужно вставить путь на 1/2 ширины линии.

Вторая проблема заключается в том, что установка слоя .cornerRadius действительно не дает ту же кривую, что и округленный прямоугольный путь Безье (странно, но это так).Итак, вам нужно создать другую маску, чтобы применить к слою кнопки.Это может привести к появлению артефактов по краям, поэтому вставьте его на 0,5 пункта.

Попробуйте этот модифицированный код:

    // create gradient layer
    let gradient = CAGradientLayer()
    gradient.frame = bounds
    gradient.colors = [UIColor(red: 0.99, green: 0.89, blue: 0.54, alpha: 1).cgColor, UIColor(red: 0.95, green: 0.51, blue: 0.51, alpha: 1).cgColor]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 1.83, y: -0.68)
    gradient.endPoint = CGPoint(x: 0.13, y: 0.82)

    // create shape for gradient layer mask
    let gradientShape = CAShapeLayer()

    // edge / line width of 6
    gradientShape.lineWidth = 6

    // border is centered on the edge, so we want to inset the rect by 1/2 of the border width
    var r = bounds.insetBy(dx: 3, dy: 3)

    // create rounded rect path
    gradientShape.path = UIBezierPath(roundedRect: r, cornerRadius: 43).cgPath

    // black stroke, clear fill
    gradientShape.strokeColor = UIColor.black.cgColor
    gradientShape.fillColor = UIColor.clear.cgColor

    // assign the shape as the gradient layer's mask
    gradient.mask = gradientShape

    // create a new shape for the button's layer
    let layerShape = CAShapeLayer()

    // inset by 0.5, to avoid artifacts on the edges
    r = bounds.insetBy(dx: 0.5, dy: 0.5)

    // create rounded rect path
    layerShape.path = UIBezierPath(roundedRect: r, cornerRadius: 43).cgPath

    // black fill (no stroke)
    layerShape.fillColor = UIColor.black.cgColor

    // assign the shape as the layer's mask
    layer.mask = layerShape

    // add gradient layer as a sublayer
    layer.addSublayer(gradient)

    setTitleColor(.red, for: .normal)
    titleLabel?.font = Theme.shared.font.bold(ofSize: 25.0)
    clipsToBounds = true
...