Анимация прозрачности части маски с помощью CAShapeLayer - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть вид с .brown backgroundColor.

. В этом виде у меня есть backgroundView, который имеет backgroundColor: UIColor.black.withAlphaComponent(0.5).

. Затем я хочу иметь прозрачныйполе в этом backgroundView, которое показывает подстилающий вид.И я достиг этого, но я не могу сделать это, анимируя его прозрачность, мой код только увеличивает «вырезанную область» до желаемого размера, а не анимирует его прозрачность.

Коричневый вид с backgroundView и его0,5 альфа

Brown view with the backgroundView and it's 0.5 alpha

Добавленный слой к backgroundView показывает часть коричневого представления

Added layer to backgroundView shows part of the brown view

Код, который я написал, чтобы получитьто, что у меня сейчас есть, это:

func addIndicatorTo(global frame: CGRect) {
    let shape = CAShapeLayer()
    let targetRect = convert(frame, from: nil).insetBy(dx: -4, dy: -4)
    let animation = CABasicAnimation(keyPath: "path")

    let toPath = CGMutablePath()
    toPath.addRect(bounds)
    toPath.addPath(UIBezierPath(roundedRect: targetRect,
                                byRoundingCorners: .allCorners,
                                cornerRadii: CGSize(width: 4, height: 4)).cgPath)
    toPath.closeSubpath()

    let fromPath = CGMutablePath()
    fromPath.addRect(bounds)
    fromPath.addPath(UIBezierPath(roundedRect: targetRect.insetBy(dx: targetRect.width / 2,
                                                                  dy: targetRect.height / 2),
                                  byRoundingCorners: .allCorners,
                                  cornerRadii: CGSize(width: 4, height: 4)).cgPath)
    fromPath.closeSubpath()

    animation.fromValue = fromPath
    animation.toValue = toPath
    animation.duration = 0.5

    shape.fillRule = .evenOdd
    shape.path = animation.fromValue as! CGPath

    backgroundView.layer.mask = shape
    shape.add(animation, forKey: nil)

    CATransaction.begin()
    CATransaction.setDisableActions(true)
    shape.path = toPath
    CATransaction.commit()
}

1 Ответ

0 голосов
/ 29 ноября 2018

Не уверен, что это "хорошее" решение.Но я буду заниматься этим до тех пор, пока кто-нибудь не скажет, покажет мне, как решить эту проблему более элегантно!

По сути, я просто создаю маску с вырезанной рамкой, а затем создаю новый boxLayer с рисунками в области«вырез».Тогда я просто оживляю opacity из boxLayer.

func addIndicatorTo(global frame: CGRect) {
    let maskLayer = CAShapeLayer()
    let boxLayer = CAShapeLayer()

    let targetRect = convert(frame, from: nil).insetBy(dx: -4, dy: -4)
    let animation = CABasicAnimation(keyPath: "opacity")

    let toPath = CGMutablePath()

    let boxPath = UIBezierPath(roundedRect: targetRect,
                               byRoundingCorners: .allCorners,
                               cornerRadii: CGSize(width: 4, height: 4)).cgPath
    toPath.addRect(bounds)
    toPath.addPath(boxPath)
    toPath.closeSubpath()

    boxLayer.fillColor = UIColor.black.withAlphaComponent(0.5).cgColor
    boxLayer.path = boxPath

    animation.fromValue = 1.0
    animation.toValue = 0.0
    animation.duration = 0.5

    maskLayer.fillRule = .evenOdd
    maskLayer.path = toPath

    backgroundView.layer.mask = maskLayer
    layer.addSublayer(boxLayer)
    boxLayer.add(animation, forKey: nil)

    CATransaction.begin()
    CATransaction.setDisableActions(true)
    boxLayer.opacity = 0.0
    CATransaction.commit()
}
...