Маска CAShapeLayer раскрывается снизу

Я пытаюсь создать эффект "раскрытия" из нижней части изображения. Я думал, что это будет так же просто, как установка anchorPoint для CGPointMake(0.5, 1.0) или contentGravity для kCAGravityTop, но ни один из этих вариантов не работает.

Текущий код у меня работает, но оживляет сверху вниз. вот идея раскрытия: http://giphy.com/gifs/xTiTnBzItdgaD1xHMc

Как бы я сделал это идти снизу вверх?

Вот код

    let path                = UIBezierPath(rect: CGRectMake(0, 0, imgEmptyBase.width, imgEmptyBase.height - 80))
    let mask                = CAShapeLayer()
    mask.anchorPoint        = CGPointMake(0.5, 1.0)
    mask.path               = path.CGPath

    imgEmptyBase.layer.mask = mask

    let anim                = CABasicAnimation(keyPath: "path")

    anim.fromValue          = path.CGPath
    anim.toValue            = UIBezierPath(rect: imgEmptyBase.bounds).CGPath
    anim.duration           = 1.0
    anim.fillMode           = kCAFillModeForwards
    anim.removedOnCompletion = false

    imgEmptyBase.layer.mask.addAnimation(anim, forKey: "anim")

4 ответа

Решение

Это достигнет именно того эффекта, который вы ищете:

let path = UIBezierPath(rect: CGRectMake(0, imgEmptyBase.layer.frame.size.height, imgEmptyBase.layer.frame.size.width, imgEmptyBase.layer.frame.size.height))
let mask = CAShapeLayer()
mask.path = path.CGPath

imgEmptyBase.layer.mask = mask

let revealPath = UIBezierPath(rect: CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, imgEmptyBase.layer.frame.size.height))

let anim                = CABasicAnimation(keyPath: "path")
anim.fromValue          = path.CGPath
anim.toValue            = revealPath.CGPath
anim.duration           = 1.0
anim.fillMode           = kCAFillModeForwards
anim.removedOnCompletion = false

imgEmptyBase.layer.mask.addAnimation(anim, forKey: "anim")

Это все об изменении пути маски, используя правильные значения "от" и "до". Например: установка начального пути маски CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, 0) и revealPath в CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, imgEmptyBase.layer.frame.size.height) приведет к эффекту "сверху вниз".

Мое предложение состоит в том, чтобы использовать штрих пути вместо заливки.

Вы рисуете траекторию (синюю линию), которая начинается в нижней части вашего слоя и заканчивается вверху, по центру по горизонтали и с шириной линии, равной ширине слоя.
Красный контур представляет контур обводки.

Вы играете анимацию на strokeEnd свойство от 0 до 1.

Я сделал игровую площадку, если вы хотите посмотреть, как мне удалось добиться такого эффекта.

Я обновил ссылку выше.
Я положил код на случай, если вы все еще не можете получить детскую площадку

let aView = UIView(frame:CGRect(x:0 y:0 width:200 height:200))
aView.backgroundColor = UIColor.redColor() // the view that needs to be masked
let shapeLayer = CAShapeLayer()
shapeLayer.bounds = aView.bounds
let bezierPath = UIBezierPath()
bezierPath.moveToPoint(CGPoint(x: shapeLayer.bounds.width/2, y: shapeLayer.bounds.height))
bezierPath.addLineToPoint(CGPoint(x: shapeLayer.bounds.width/2, y: 0))
shapeLayer.path = bezierPath.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = UIColor.redColor().CGColor
shapeLayer.lineWidth = shapeLayer.bounds.width
shapeLayer.position = CGPoint(x: aView.frame.width/2, y: aView.frame.height/2)
shapeLayer.strokeEnd = 1

let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 4
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
shapeLayer.addAnimation(animation, forKey: "stroneAnimation")
shapeLayer.strokeEnd = 1
aView.layer.mask = shapeLayer

Проверь это!!

let path = UIBezierPath(rect: CGRectMake(0, denterImage.frame.origin.y, denterImage.bounds.size.width, denterImage.bounds.size.height - 200))
let mask = CAShapeLayer()
mask.anchorPoint = CGPointMake(0.5, 1.0)
mask.path = path.CGPath

denterImage.layer.mask = mask

let anim = CABasicAnimation(keyPath: "path")

anim.fromValue = path.CGPath
anim.toValue = UIBezierPath(rect: denterImage.bounds).CGPath
anim.duration =  1.5
anim.fillMode = kCAFillModeForwards
anim.removedOnCompletion = false

denterImage.layer.mask.addAnimation(anim, forKey: "anim")

Есть (2) варианты, которые приходят на ум.

Одним из них является просто переключение анимации с и на значения:

let path                = UIBezierPath(rect: CGRectMake(0, 0, imgEmptyBase.width, imgEmptyBase.height - 80))
let mask                = CAShapeLayer()
mask.anchorPoint        = CGPointMake(0.5, 1.0)
mask.path               = path.CGPath

imgEmptyBase.layer.mask = mask

let anim                = CABasicAnimation(keyPath: "path")

anim.fromValue          = UIBezierPath(rect: imgEmptyBase.bounds).CGPath
anim.toValue            = path.CGPath
anim.duration           = 1.0
anim.fillMode           = kCAFillModeForwards
anim.removedOnCompletion = false

imgEmptyBase.layer.mask.addAnimation(anim, forKey: "anim")

Другой заключается в том, чтобы переключать сами объявления пути Безье:

let path                = UIBezierPath(rect: imgEmptyBase.bounds).CGPath
let mask                = CAShapeLayer()
mask.anchorPoint        = CGPointMake(0.5, 1.0)
mask.path               = path.CGPath

imgEmptyBase.layer.mask = mask

let anim                = CABasicAnimation(keyPath: "path")

anim.fromValue          = path.CGPath
anim.toValue            = UIBezierPath(rect: CGRectMake(0, 0, imgEmptyBase.width, imgEmptyBase.height - 80))
anim.duration           = 1.0
anim.fillMode           = kCAFillModeForwards
anim.removedOnCompletion = false

imgEmptyBase.layer.mask.addAnimation(anim, forKey: "anim")
Другие вопросы по тегам