CAShapeLayer 遮罩从底部显示
CAShapeLayer mask reveal from bottom
我正在尝试从图像底部创建 "reveal" 效果。
我认为这就像将 anchorPoint 设置为 CGPointMake(0.5, 1.0) 或将 contentsGravity 设置为 kCAGravityTop 一样简单,但是 none 这些选项有效。
我的当前代码有效,但从上到下进行动画处理。这是揭示的想法: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")
我想到了 (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")
检查这个!!
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")
我的建议是使用路径的描边而不是填充。
你画了一条路径(蓝线),从图层底部开始到顶部结束,水平居中,线宽相同作为图层宽度。
红色轮廓代表笔划轮廓。
你在 strokeEnd
属性 上播放一个从 0 到 1 的动画。
I made a playground 如果你想看看我是如何做到这一点的。
我更新了上面的link。
我放了代码以防你仍然无法进入游乐场
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, 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")
一切都是关于使用正确的 "from" 和 "to" 值更改蒙版路径。例如:将初始遮罩路径设置为 CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, 0)
并将 revealPath
设置为 CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, imgEmptyBase.layer.frame.size.height)
将导致 "top to bottom" 显示效果。
我正在尝试从图像底部创建 "reveal" 效果。 我认为这就像将 anchorPoint 设置为 CGPointMake(0.5, 1.0) 或将 contentsGravity 设置为 kCAGravityTop 一样简单,但是 none 这些选项有效。
我的当前代码有效,但从上到下进行动画处理。这是揭示的想法: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")
我想到了 (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")
检查这个!!
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")
我的建议是使用路径的描边而不是填充。
你画了一条路径(蓝线),从图层底部开始到顶部结束,水平居中,线宽相同作为图层宽度。
红色轮廓代表笔划轮廓。
你在 strokeEnd
属性 上播放一个从 0 到 1 的动画。
I made a playground 如果你想看看我是如何做到这一点的。
我更新了上面的link。
我放了代码以防你仍然无法进入游乐场
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, 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")
一切都是关于使用正确的 "from" 和 "to" 值更改蒙版路径。例如:将初始遮罩路径设置为 CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, 0)
并将 revealPath
设置为 CGRectMake(0, 0, imgEmptyBase.layer.frame.size.width, imgEmptyBase.layer.frame.size.height)
将导致 "top to bottom" 显示效果。