Ios 如何在UIBezierPath上设置填充颜色更改的动画?

Ios 如何在UIBezierPath上设置填充颜色更改的动画?,ios,swift,Ios,Swift,形状一开始是正确填充的,但我不知道如何更改填充颜色,或者更好的是,如何在UIBezierPath上设置填充颜色更改的动画。就像更改UIView的背景色一样,我正在寻找 var fillColor = UIColor() func changeBackgroundColor() { let animcolor = CABasicAnimation(keyPath: "fillColor") animcolor.fromValue = UIColor.greenColor()

形状一开始是正确填充的,但我不知道如何更改填充颜色,或者更好的是,如何在
UIBezierPath
上设置填充颜色更改的动画。就像更改UIView的背景色一样,我正在寻找

var fillColor = UIColor()

func changeBackgroundColor() {

    let animcolor = CABasicAnimation(keyPath: "fillColor")
    animcolor.fromValue = UIColor.greenColor()
    animcolor.toValue = UIColor.orangeColor()
    animcolor.duration = 1.0;
    animcolor.repeatCount = 0;
    animcolor.autoreverses = true
    shapeLayer.addAnimation(animcolor, forKey: "fillColor")

}


var fillColor = UIColor()
let clipPath = UIBezierPath()
let shapeLayer = CAShapeLayer()

override func drawRect(rect: CGRect) {

        clipPath.moveToPoint(CGPointMake(self.bounds.minX + 7.65, self.bounds.minY - 0.25))
        clipPath.addCurveToPoint(CGPointMake(self.bounds.minX + 7.65, self.bounds.minY + 36.1), controlPoint1: CGPointMake(self.bounds.minX - 2.38, self.bounds.minY + 9.79), controlPoint2: CGPointMake(self.bounds.minX - 2.38, self.bounds.minY + 26.06))
        clipPath.addCurveToPoint(CGPointMake(self.bounds.minX + 43.99, self.bounds.minY + 36.1), controlPoint1: CGPointMake(self.bounds.minX + 17.69, self.bounds.minY + 46.13), controlPoint2: CGPointMake(self.bounds.minX + 33.96, self.bounds.minY + 46.13))
        clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 43.99, self.bounds.minY + 36.1))
        clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 44.01, self.bounds.minY + 0.19))
        clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 7.58, self.bounds.minY + 0.19))
        clipPath.usesEvenOddFillRule = true
        fillColor = userColor
    }

clipPath.addClip()
fillColor.setFill()
clipPath.fill()
shapeLayer.path = clipPath.CGPath
self.layer.mask = shapeLayer
就像更改UIView的背景色一样,我正在寻找

var fillColor = UIColor()

func changeBackgroundColor() {

    let animcolor = CABasicAnimation(keyPath: "fillColor")
    animcolor.fromValue = UIColor.greenColor()
    animcolor.toValue = UIColor.orangeColor()
    animcolor.duration = 1.0;
    animcolor.repeatCount = 0;
    animcolor.autoreverses = true
    shapeLayer.addAnimation(animcolor, forKey: "fillColor")

}


var fillColor = UIColor()
let clipPath = UIBezierPath()
let shapeLayer = CAShapeLayer()

override func drawRect(rect: CGRect) {

        clipPath.moveToPoint(CGPointMake(self.bounds.minX + 7.65, self.bounds.minY - 0.25))
        clipPath.addCurveToPoint(CGPointMake(self.bounds.minX + 7.65, self.bounds.minY + 36.1), controlPoint1: CGPointMake(self.bounds.minX - 2.38, self.bounds.minY + 9.79), controlPoint2: CGPointMake(self.bounds.minX - 2.38, self.bounds.minY + 26.06))
        clipPath.addCurveToPoint(CGPointMake(self.bounds.minX + 43.99, self.bounds.minY + 36.1), controlPoint1: CGPointMake(self.bounds.minX + 17.69, self.bounds.minY + 46.13), controlPoint2: CGPointMake(self.bounds.minX + 33.96, self.bounds.minY + 46.13))
        clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 43.99, self.bounds.minY + 36.1))
        clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 44.01, self.bounds.minY + 0.19))
        clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 7.58, self.bounds.minY + 0.19))
        clipPath.usesEvenOddFillRule = true
        fillColor = userColor
    }

clipPath.addClip()
fillColor.setFill()
clipPath.fill()
shapeLayer.path = clipPath.CGPath
self.layer.mask = shapeLayer
但你为什么不能做到呢?您已经将视图遮罩到您的路径,因此设置背景颜色动画将获得您想要的确切效果。只需去掉核心图形路径填充,并根据需要删除
drawRect
覆盖即可

如果你真的需要使用<代码> DRACORT 并激活该颜色,你可以考虑将你的<代码> uiVIEW/CODE分割成两个<代码> uiVIEW/COD>——一个绘制背景层(你可以动画),一个绘制自定义图。或者,您可以设置一个

CADisplayLink
,以使用中间背景色重新绘制每个帧的视图,但这在性能方面并不令人惊讶

正如我在下面所说的,您不能直接为
UIBezierPath
的填充颜色设置动画。如果只想用现有代码更改填充颜色(而不是设置动画),则只需使用不同的
userColor
调用
setNeedsDisplay

如果你问这个问题是因为你使用了两种不同的路径进行掩蔽和填充,请参阅下面我的答案(事后看来过于复杂)


问题是
UIBezierPath
的填充颜色不可设置动画。但是
CAShapeLayer
上的填充颜色为

因此,您需要使用另一个
CAShapeLayer
进行填充。我建议您创建一个
fillLayer
和一个
maskLayer
属性,以明确它们的功能。现在,由于您使用的是100%分层方法,您可以将代码移出
drawRect
,因为您不再进行任何核心图形绘制

另外,值得注意的是,您需要使用
CGColor
作为动画的往返值

像这样的事情应该可以做到:

var fillColor = UIColor.greenColor()
let maskLayer = CAShapeLayer()
let fillLayer = CAShapeLayer()

func changeBackgroundColor() {

    let animcolor = CABasicAnimation(keyPath: "fillColor")
    animcolor.fromValue = UIColor.greenColor().CGColor
    animcolor.toValue = UIColor.orangeColor().CGColor
    animcolor.duration = 1.0;
    animcolor.repeatCount = 0;
    animcolor.autoreverses = true
    fillLayer.addAnimation(animcolor, forKey: "fillColor")

}

// re-adjust the clipping path when the view bounds changes
override func layoutSubviews() {

    let clipPath = UIBezierPath()
    clipPath.moveToPoint(CGPointMake(self.bounds.minX + 7.65, self.bounds.minY - 0.25))
    clipPath.addCurveToPoint(CGPointMake(self.bounds.minX + 7.65, self.bounds.minY + 36.1), controlPoint1: CGPointMake(self.bounds.minX - 2.38, self.bounds.minY + 9.79), controlPoint2: CGPointMake(self.bounds.minX - 2.38, self.bounds.minY + 26.06))
    clipPath.addCurveToPoint(CGPointMake(self.bounds.minX + 43.99, self.bounds.minY + 36.1), controlPoint1: CGPointMake(self.bounds.minX + 17.69, self.bounds.minY + 46.13), controlPoint2: CGPointMake(self.bounds.minX + 33.96, self.bounds.minY + 46.13))
    clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 43.99, self.bounds.minY + 36.1))
    clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 44.01, self.bounds.minY + 0.19))
    clipPath.addLineToPoint(CGPointMake(self.bounds.minX + 7.58, self.bounds.minY + 0.19))

    // update layer paths
    fillLayer.path = clipPath.CGPath
    maskLayer.path = clipPath.CGPath

}

override init(frame: CGRect) {
    super.init(frame: frame)

    // configure filling
    fillLayer.fillColor = fillColor.CGColor
    fillLayer.fillRule = kCAFillRuleEvenOdd

    // add fill path to superlayer
    layer.addSublayer(fillLayer)

    // configure masking layer
    maskLayer.fillRule = kCAFillRuleEvenOdd
    layer.mask = maskLayer
}

Swift 4版,你可以在操场上查看代码

var fillColor=UIColor.green
设maskLayer=CAShapeLayer()
设fillLayer=CAShapeLayer()
func changeBackgroundColor(){
让animcolor=cabasicanitation(关键路径:“fillColor”)
animcolor.fromValue=UIColor.green.cgColor
animcolor.toValue=UIColor.orange.cgColor
animcolor.duration=1.0;
animcolor.repeatCount=0;
animcolor.autoreverses=true
添加(animcolor,forKey:“fillColor”)
}
//视图边界更改时重新调整剪裁路径
let view=ui视图(帧:CGRect(x:0,y:0,宽度:300,高度:300))
view.backgroundColor=UIColor.white
func createpath(){
设clipPath=UIBezierPath()
移动(到:CGPoint(x:view.bounds.minX+7.65,y:view.bounds.minY-0.25))
clipPath.addCurve(to:CGPoint(x:view.bounds.minX+7.65,y:view.bounds.minY+36.1),
控制点1:CGPoint(x:view.bounds.minX-2.38,y:view.bounds.minY+9.79),
控制点2:CGPoint(x:view.bounds.minX-2.38,y:view.bounds.minY+26.06))
clipPath.addCurve(to:CGPoint(x:view.bounds.minX+43.99,y:view.bounds.minY+36.1),
控制点1:CGPoint(x:view.bounds.minX+17.69,y:view.bounds.minY+46.13),
控制点2:CGPoint(x:view.bounds.minX+33.96,y:view.bounds.minY+46.13))
clipPath.addLine(to:CGPoint(x:view.bounds.minX+43.99,y:view.bounds.minY+36.1))
clipPath.addLine(to:CGPoint(x:view.bounds.minX+44.01,y:view.bounds.minY+0.19))
clipPath.addLine(to:CGPoint(x:view.bounds.minX+7.58,y:view.bounds.minY+0.19))
//更新图层路径
fillLayer.path=clipPath.cgPath
maskLayer.path=clipPath.cgPath
fillLayer.fillColor=fillColor.cgColor
fillLayer.fillRule=.evenOdd
view.layer.addSublayer(fillLayer)
maskLayer.fillRule=.evenOdd
view.layer.mask=maskLayer
}

CreatePath()
太棒了。感谢您为更好的实施而努力。然而,我无法获得
fillLayer
的填充颜色来设置动画,我甚至无法更改它。该函数肯定正在被调用,我正在记录它以确保。这就是我坐下来想在30-40分钟内完成的事情,结果花了半天的时间。@spacemonkey是
fillLayer
在制作动画之前显示在屏幕上的吗?确保其
frame
为非零,并将其添加到图层层次结构中。如果您使用的是我上面的代码,则需要使用
init(frame:)
初始化器初始化
UIView
(实际上,您希望将任何与大小相关的代码移动到更合适的位置,例如
layoutSubviews
)。确切的位置和大小,它应该是。填充颜色也被设置为它应该的颜色,它只是不会改变为其他颜色。嗯。。。奇怪的在一个测试项目中,上面的代码对我来说运行良好。你确定把
.CGColor
添加到动画的“到”和“从”值中了吗?我知道,没错,这太疯狂了。甚至注释掉整个类并逐字输入。