我正在尝试在UIView上设置遮罩层的动画。
此代码基本上显示以下图片:
let bounds: CGRect = self.manualWBMaskView!.bounds
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.fillColor = UIColor.blackColor().CGColor
let screenWith : CGFloat = UIScreen.mainScreen().bounds.width
let roundedRectFrame : CGRect = CGRectMake(self.manualWBMaskView!.bounds.midX - (screenWith/4), self.manualWBMaskView!.bounds.midY - (screenWith/4), screenWith/2, screenWith/2)
let path: UIBezierPath = UIBezierPath(roundedRect:roundedRectFrame, cornerRadius:10 )
path.appendPath(UIBezierPath(rect: bounds))
maskLayer.path = path.CGPath
maskLayer.fillRule = kCAFillRuleEvenOdd
self.manualWBMaskView!.layer.mask = maskLayer
我想让它从全屏到以上位置动画到切口的位置:
我试过UIView动画,没有运气。既然我已经有了CAShapeLayer,我应该能够为它制作动画吗?
编辑**
这是我尝试的动画代码,但没有用:
//Before Animation Make the Mask fill the whole view:
self.manualWBMaskView!.layer.mask = self.manualWBMaskView!.bounds
var duration: NSTimeInterval = 0.8
CATransaction.begin()
CATransaction[kCATransactionAnimationDuration] = Int(duration)
self.manualWBMaskView!.layer.mask = CGRectMake(self.manualWBMaskView!.bounds.midX - (screenWith/4), self.manualWBMaskView!.bounds.midY - (screenWith/4), screenWith/2, screenWith/2)
CATransaction.commit()
根据'originaluser2的回复,我有这个:
func presentMaskScreenWithAnimation () {
let bounds: CGRect = self.manualWBMaskView!.bounds
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.fillColor = UIColor.blackColor().CGColor
let screenWith : CGFloat = UIScreen.mainScreen().bounds.width
let roundedRectFrame : CGRect = self.manualWBMaskView.bounds
let path: UIBezierPath = UIBezierPath(roundedRect:roundedRectFrame, cornerRadius:0 )
path.appendPath(UIBezierPath(rect: bounds))
maskLayer.path = path.CGPath
maskLayer.fillRule = kCAFillRuleEvenOdd
self.manualWBMaskView!.layer.mask = maskLayer
// define your new path to animate the mask layer to
let screenWith2 : CGFloat = UIScreen.mainScreen().bounds.width
let roundedRectFrame2 : CGRect = CGRectMake(self.manualWBMaskView!.bounds.midX - (screenWith2/4), self.manualWBMaskView!.bounds.midY - (screenWith2/4), screenWith2/2, screenWith2/2)
let path2 = UIBezierPath(roundedRect:roundedRectFrame2, cornerRadius:10 )
// create new animation
let anim = CABasicAnimation(keyPath: "path")
// from value is the current mask path
anim.fromValue = maskLayer.path
// to value is the new path
anim.toValue = path2.CGPath
// duration of your animation
anim.duration = 5.0
// custom timing function to make it look smooth
anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
// add animation
maskLayer.addAnimation(anim, forKey: nil)
// update the path property on the mask layer, using a CATransaction to prevent an implicit animation
CATransaction.begin()
CATransaction.setDisableActions(true)
maskLayer.path = path2.CGPath
maskLayer.fillRule = kCAFillRuleEvenOdd
CATransaction.commit()
}
它做动画;但是,我现在有两个问题: 1.动画期间形状全部关闭,但如果在动画结束时聚集在一起。 (以下截图)
答案 0 :(得分:19)
CABasicAnimation
属性中使用path
这将允许您将遮罩从给定路径动画到另一个给定路径。核心动画将自动为您插入中间步骤。
这样的事情可以解决问题:
// define your new path to animate the mask layer to
let path = UIBezierPath(roundedRect: CGRectInset(view.bounds, 100, 100), cornerRadius: 20.0)
path.appendPath(UIBezierPath(rect: view.bounds))
// create new animation
let anim = CABasicAnimation(keyPath: "path")
// from value is the current mask path
anim.fromValue = maskLayer.path
// to value is the new path
anim.toValue = path.CGPath
// duration of your animation
anim.duration = 5.0
// custom timing function to make it look smooth
anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
// add animation
maskLayer.addAnimation(anim, forKey: nil)
// update the path property on the mask layer, using a CATransaction to prevent an implicit animation
CATransaction.begin()
CATransaction.setDisableActions(true)
maskLayer.path = path.CGPath
CATransaction.commit()
<强>结果:强>
有一点需要注意的是,核心动画中似乎存在一个错误,它无法从包含矩形的路径正确动画到包含带圆角半径的圆角矩形的路径。我已经向Apple提交了一份错误报告。
有一个简单的解决方法,就是在原始路径上使用圆角矩形,角半径可忽略不计(0.0001对我来说没问题)。有点hacky - 但是在使用应用程序时你无法注意到它的区别。
不幸的是,Apple认为这是&#34;预期的行为&#34;。他们说了以下几点:
要使动画正确渲染,动画路径应具有相同数量的元素/片段(理想情况下为相同类型)。否则,没有合理的方法在两者之间进行插值。
例如,如果第一条路径有四个元素而第二条路径有六个元素,我们可以通过平均前四个起点和终点以及当前时间的权重来轻松创建前四个点,但它是“不可能想出一个通用的方法来计算第五和第六点的中间位置。这就是为什么动画在角半径0.001(相同数量的元素)下工作得很好,但对于普通矩形路径(不同数量的元素)则失败。
我个人不同意,如果指定圆角半径为0的圆角,然后动画为圆角矩形,角半径> 0 - 仍然获得了不正确的动画,即使两个路径应该具有相同数量的元素&#34;。我怀疑这不起作用的原因是内部实现检查半径为0,并尝试使用带有4个元素的矩形路径进行优化,这就是为什么它不起作用。
当我抽出时间时,我会提交另一份错误报告来解释这一点。
你强行解开你的manualWBMaskView
。唐&#39;吨。您需要了解如何properly deal with optionals。每次你强行解开东西 - 你的应用程序都可能崩溃。
您还有以下几行:
let maskLayer: CAShapeLayer = CAShapeLayer()
这里的: CAShapeLayer
不仅是不必要的 - 而且违背了良好的做法。你应该总是让Swift推断它可以的值的类型。