为啥我的 CAShapeLayer 无法使用 UIView(带 gif)正确设置动画?

Posted

技术标签:

【中文标题】为啥我的 CAShapeLayer 无法使用 UIView(带 gif)正确设置动画?【英文标题】:Why is my CAShapeLayer not animating correctly with the UIView (w/ gif)?为什么我的 CAShapeLayer 无法使用 UIView(带 gif)正确设置动画? 【发布时间】:2017-11-09 17:17:03 【问题描述】:

好的,事情就是这样。

灰色区域是一个 UIView,并用CAShapeLayer 掩盖了它。我附加了两个UIBezierPath 并使用Even Odd Rule 删除了该灰色区域的一部分。这就是为什么它显示一条线,就好像它在左侧显示一个半圆。

红色背景只是容器视图。

现在我的问题是,当我为UIView 设置动画时,就好像在为UIView 设置动画时面具没有正确更新。

这是UIView 动画部分:

func didCompleteItem() 
    self.bar.plainProgressBarLeftAnchor?.constant = self.bar.bounds.width * (self.completedItemCount*self.barMeterMultiplier) / self.bar.bounds.width - self.bar.meterCornerRadius
    UIView.animate(withDuration: 1.0, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .curveEaseInOut, animations: 
        self.bar.layoutIfNeeded()

    , completion: nil)

现在,这里是 layoutSubviews 的一部分,如果您需要查看 CAShapeLayer 是如何创建的。

override func layoutSubviews() 
    super.layoutSubviews()

    backgroundColor = GradientColor(.leftToRight, frame: self.bounds, colors: GradientFlatRed())
    layer.masksToBounds = true
    layer.cornerRadius = meterCornerRadius

    createMask()



var shapeLayer: CAShapeLayer = CAShapeLayer()
func createMask() 
    let bPath = UIBezierPath(roundedRect: plainProgressBar.bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width: 0, height: 0))
    let semiCircle = UIBezierPath(arcCenter: CGPoint(x: bounds.origin.x, y: plainProgressBar.bounds.origin.y+meterCornerRadius), radius: meterCornerRadius, startAngle: 3 * CGFloat.pi / 2, endAngle: CGFloat.pi / 2, clockwise: true)
    shapeLayer.frame = layer.bounds
    bPath.append(semiCircle)
    shapeLayer.path = bPath.cgPath
    shapeLayer.fillRule = kCAFillRuleEvenOdd
    plainProgressBar.layer.mask = shapeLayer

【问题讨论】:

我不会只画一个半圆,而是画一个完整的圆来避免这个问题。另外,也许在layoutLayer()(相当于layoutSubView)中可能有助于修复它。 为什么layoutLayer() 会解决它?和视图的生命周期有关系吗? 【参考方案1】:

绘制一个可拉伸的圆圈并更改描绘圆圈的图像视图的宽度将为您提供您所追求的效果,几乎不费吹灰之力,也没有您遇到的任何伪影:

【讨论】:

我减少灰色区域而不是制作可拉伸的红色圆圈的原因是因为我的红色背景是渐变色。我可以使用您的方法并为圆圈添加渐变,但它不符合我的设计选择。它总是看起来像一个渐变圆,即使我拉伸它,如果你知道我的意思的话。换句话说,我希望红色背景使它看起来像是逐渐变成深红色。这就是故障在右侧显示较深红色的原因。 那么我认为你的问题提出的不是很清楚。但是,在 Stack Overflow 上已经很好地处理了遮罩到渐变以及更改遮罩的形状。 不过,我认为这并没有显着改变我的答案。蒙版可以是蒙版视图,蒙版视图可以是图像视图,因此您可以按照我建议的方式为蒙版设置动画。 修改了我的屏幕截图,以显示将 image-view-as-mask 设置为动画效果完全符合您的要求。只需调整渐变细节,您就可以回家了。

以上是关于为啥我的 CAShapeLayer 无法使用 UIView(带 gif)正确设置动画?的主要内容,如果未能解决你的问题,请参考以下文章

iOS之UI--CAShapeLayer

为啥我无法使用 CAGradientLayer 的掩码

为啥 CAShapeLayer 的笔触会延伸到框架之外?

iOS开发UI篇——Core Animation核心动画CAShapeLayer(绘制图形等)简介

带有 CAShapeLayer 的 UIView 不显示 CAGradientLayer

为啥我的页面上没有出现 JQuery UI 滑块?