CALayers неправильно трансформируются при вращении - PullRequest
0 голосов
/ 25 апреля 2019

Учитывая расположение слоев CAL, как показано слева (фон, рамка и текстовый слой), я хочу повернуть два из них на 45 ° (layer.transform = CATransform3DMakeRotation(.pi / 4, 0, 0, 1)), в результате чего ромб будет справа, ното, что я вижу, - это диагональная линия посередине.

Unrotated, rotated, expected

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

class ScoreLayer: CALayer {
    var score = 0 {
        didSet {
            updateValue()
        }
    }

    let bgLayer: CALayer = {
        let layer = CALayer()
        layer.contentsScale = UIScreen.main.scale
        layer.backgroundColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
        layer.shadowOffset = .zero
        layer.shadowRadius = 3
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOpacity = 0.4
        return layer
    }()

    let textLayer: CATextLayer = {
        let layer = CATextLayer()
        layer.contentsScale = UIScreen.main.scale
        layer.alignmentMode = .center
        layer.foregroundColor = UIColor.white.cgColor
        layer.fontSize = 20
        layer.font = UIFont.preferredFont(forTextStyle: .largeTitle)
        return layer
    }()

    let frameLayer: CALayer = {
        let layer = CALayer()
        layer.contentsScale = UIScreen.main.scale
        layer.borderColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
        layer.borderWidth = 3
        layer.shadowOffset = .zero
        layer.shadowRadius = 3
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOpacity = 0.7
        return layer
    }()

    override init() {
        super.init()
        contentsScale = UIScreen.main.scale

        addSublayer(bgLayer)
        addSublayer(textLayer)
        addSublayer(frameLayer)

        updateValue()
    }

    override func layoutSublayers() {
        bgLayer.frame = bounds
        frameLayer.frame = bounds
        textLayer.frame = bounds

        bgLayer.transform = CATransform3DMakeRotation(.pi / 4, 0, 0, 1)
        frameLayer.transform = CATransform3DMakeRotation(.pi / 4, 0, 0, 1)
    }

    private func updateValue() {
        textLayer.string = "\(score)"
    }
}

Анимация вращения (путем установки нового преобразования с помощью CADisplayLink) это выглядит так, как будто вращающиеся слои также вращаются вокруг своей оси X.Я не устанавливаю никаких преобразований, кроме двух в листинге кода.

Что вызывает это?

1 Ответ

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

Не обновлять фрейм после применения преобразования.layoutSublayers вызывается несколько раз, и эффект смешивания приводит к нежелательному искажению.Установите кадр один раз в другом месте перед применением преобразования или, если требуется обновление кадра (возможно, в ответ на изменение ориентации), обязательно удалите обновление преобразования кадра и затем повторно примените преобразование.

Отредактировано, чтобы добавить:

документы фактически явно говорят "Не устанавливайте фрейм, если свойство преобразования применяет преобразование вращения, которое не кратно 90 градусам. "

...