Ios 动画CALayer';s阴影路径特性

Ios 动画CALayer';s阴影路径特性,ios,animation,calayer,shadow,Ios,Animation,Calayer,Shadow,我知道CALayer的阴影路径只能使用显式动画来设置动画,但是我仍然无法使其工作。我怀疑我没有正确地传递toValue——据我所知,这必须是一个id,但属性采用CGPathRef。将其存储在UIBezierPath中似乎不起作用。我正在使用以下代码进行测试: CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"]; theAnimation.duration = 3.0; the

我知道CALayer的阴影路径只能使用显式动画来设置动画,但是我仍然无法使其工作。我怀疑我没有正确地传递
toValue
——据我所知,这必须是一个
id
,但属性采用CGPathRef。将其存储在
UIBezierPath
中似乎不起作用。我正在使用以下代码进行测试:

CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"];
theAnimation.duration = 3.0;
theAnimation.toValue = [UIBezierPath bezierPathWithRect:CGRectMake(-10.0, -10.0, 50.0, 50.0)];
[self.view.layer addAnimation:theAnimation forKey:@"animateShadowPath"];
(我使用的是负值,以确保阴影延伸到位于阴影上方的视图之外……该层的
masksToBounds
属性设置为
NO

阴影路径的动画是如何实现的

更新

问题几乎解决了。不幸的是,主要问题是有点粗心的错误

我犯的错误是将动画添加到视图控制器的根层,而不是我专用于阴影的层。另外,@pe8ter是正确的,
toValue
需要是一个
CGPathRef
转换为
id
(显然,当我之前尝试过这个时,由于错误的层错误,我仍然没有动画)。动画使用以下代码工作:

CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"];
theAnimation.duration = 3.0;
theAnimation.toValue = (id)[UIBezierPath bezierPathWithRect:myRect].CGPath;
[controller.shadowLayer addAnimation:theAnimation forKey:@"shadowPath"];
我理解从我提供的示例代码中很难发现这一点。不过,希望它对处于类似情况的人仍然有用

但是,当我尝试添加行时

controller.shadowLayer.shadowPath = [UIBezierPath bezierPathWithRect:myRect].CGPath;

动画停止工作,阴影立即跳到最终位置。文档说添加与正在更改的属性具有相同关键点的动画,以便覆盖在设置属性值时创建的隐式动画,但是shadowPath无法生成隐式动画。。。那么,如何在动画之后保留新属性?

首先,您没有设置动画的
fromValue

其次,您是正确的:
toValue
接受一个
CGPathRef
,但它需要强制转换为
id
。这样做:

theAnimation.toValue = (id)[UIBezierPath bezierPathWithRect:newRect].CGPath;

如果要在动画结束后保留更改,还需要显式设置层的
阴影路径
属性。

我遇到了阴影动画的相同问题,并找到了在动画结束后保留阴影的解决方案。在开始动画之前,需要设置阴影层的最终路径。由于CoreAnimation不会更新原始层的属性,因此会恢复到初始阴影,它会创建此层的副本并在此副本上显示动画()。动画结束后,系统删除该动画层并返回原始层,该层未更新路径,并显示旧阴影。请尝试以下代码:

let cornerRadious = 10.0
        //
        let shadowPathFrom = UIBezierPath(roundedRect: rect1, cornerRadius: cornerRadious)
        let shadowPathTo = UIBezierPath(roundedRect: rect2, cornerRadius: cornerRadious)
        //
        layer.masksToBounds = false
        layer.shadowColor = UIColor.yellowColor().CGColor
        layer.shadowOpacity = 0.6
        //
        let shadowAnimation = CABasicAnimation(keyPath: "shadowPath")
        shadowAnimation.fromValue = shadowPathFrom.CGPath
        shadowAnimation.toValue = shadowPathTo.CGPath
        shadowAnimation.duration = 0.4
        shadowAnimation.autoreverses = true
        shadowAnimation.removedOnCompletion = true
        shadowAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        layer.addAnimation(shadowAnimation, forKey: "shadowAnimation")
    let shadowAnimation = CABasicAnimation(keyPath: "shadowPath")
    shadowAnimation.fromValue = currentShadowPath
    shadowAnimation.toValue = newShadowPath
    shadowAnimation.duration = 3.0

    shadowLayer.shadowPath = newShadowPath
    shadowLayer.add(shadowAnimation, forKey: "shadowAnimation")

虽然不能直接回答这个问题,但如果你只需要一个可以投射阴影的视图,你可以直接使用我的类

/*
斯威夫特
版权所有©2018、2020-2021 BB9z
https://github.com/BB9z/iOS-Project-Template
麻省理工学院执照
https://opensource.org/licenses/MIT
*/
/**
景色投下阴影。
*/
@可设计的
类ShadowView:UIView{
@IBInspectable var shadowOffset:CGPoint=CGPoint(x:0,y:8){
didSet{needsUpdateStyle=true}
}
@IBInspectable var shadowBlur:CGFloat=10{
didSet{needsUpdateStyle=true}
}
@IBInspectable var shadowSpread:CGFloat=0{
didSet{needsUpdateStyle=true}
}
///设置为零可以禁用阴影
@IBInspectable var shadowColor:UIColor?=UIColor.black.withAlphaComponent(0.3){
didSet{needsUpdateStyle=true}
}
@i可检测的var角半径:CGFloat{
获取{layer.cornerRadius}
设置{layer.cornerRadius=newValue}
}
私有变量needsUpdateStyle=false{
迪塞特{
guard needsUpdateStyle,!oldValue else{return}
DispatchQueue.main.async{[self]位于
如果需要UpdateStyle{updateLayerStyle()}
}
}
}
private func updateLayerStyle(){
needsUpdateStyle=false
如果let color=shadowColor{
阴影(视图:自身、偏移:阴影偏移、模糊:阴影模糊、扩散:阴影扩散、颜色:颜色、拐角半径:拐角半径)
}否则{
layer.shadowColor=nil
layer.shadowPath=nil
layer.shadowOpacity=0
}
}
重写func prepareForInterfaceBuilder(){
super.prepareforPrinterFaceBuilder()
updateLayerStyle()
}
覆盖func layoutSublayers(图层的名称:CALayer){
超级布局子层(共层)
lastLayerSize=layer.bounds.size
如果shadowColor!=nil,layer.shadowOpacity==0{
updateLayerStyle()
}
}
私有变量lastLayerSize=CGSize.zero{
迪塞特{
如果oldValue==lastLayerSize{return}
保护阴影颜色!=nil else{return}
updateShadowPathWithAnimationFixes(bonuds:layer.bounds)
}
}
//在调整视图大小时,我们需要一些额外的步骤来实现平滑的结果
private func updateShadowPathWithAnimationFixes(bonuds:CGRect){
设rect=bonuds.insertby(dx:shadowSpread,dy:shadowSpread)
让newShadowPath=UIBezierPath(roundedRect:rect,cornerRadius:cornerRadius).cgPath
如果让resizeAnimation=layer.animation(forKey:“bounds.size”){
let key=#keyPath(CALayer.shadowPath)
让阴影动画=cabasicanition(关键路径:关键点)
shadowAnimation.duration=调整大小animation.duration
shadowAnimation.timingFunction=调整大小Animation.timingFunction
shadowAnimation.fromValue=layer.shadowPath
shadowAnimation.toValue=newShadowPath
添加(阴影动画,forKey:key)
}
layer.shadowPath=newShadowPath
}
}
/**
使用与草图应用程序相同的效果制作阴影。
*/
func阴影(视图:UIView?,偏移:CGPoint,模糊:CGFloat,排列:CGFloat,颜色:UIColor,角半径:CGFloat=0){//swiftlint:disable:此标识符