如何使 CAGradientLayer 遵循 CGPath

Posted

技术标签:

【中文标题】如何使 CAGradientLayer 遵循 CGPath【英文标题】:How to make a CAGradientLayer follow a CGPath 【发布时间】:2018-10-05 14:36:38 【问题描述】:

给定一个定义如下图路径的 CAShapeLayer,我想添加一个 CAGradientLayer 跟随形状层的路径。

例如,给定从黑色到红色的渐变:

右上角的圆形部分是黑色的, 如果滑块在 100,左上角会是红色的, 如果滑块位于 50,则滑块的一半将是黑色(如下所示),可见渐变将从黑色(右上角)变为底部的红黑色

我发现的每个以前的帖子实际上都没有回答这个问题。 例如,因为我只能添加轴向 CAGradientLayers,我可以这样做(下图),但您可以看到它不正确(左上角最终再次变黑)。如何使渐变实际上遵循路径/蒙版

【问题讨论】:

正如您所发现的,这个问题已经被问过很多次了——据我所知,从来没有人回答过。我开始认为这是不可能的……但也许这一次谜团会被破解! 我当然希望如此!一堆帖子提到了 CAGradientLayerType 仅具有 .axis 作为选项这一事实 - 但现在还有两个额外的(.radial 和 .conic)所以我充满希望,尽管仍然没有解决问题:O. 这可能值得一看:github.com/sfcd/SFProgressCircle 还有一个:github.com/robertpankrath/GradientRingProgressView 检查 awesome-gradient 以查找使用 CAGradientLayer 的 ios 示例遵循 CGPath github.com/cruisediary/awesome-gradient 【参考方案1】:

对于简单的圆形路径,新的圆锥渐变很棒。我能够立即得到这个(这是一个被圆形图层掩盖的圆锥渐变图层):

我使用了红色和绿色,以便清楚地显示渐变。这似乎与您所追求的不一样,但我不敢相信既然存在.conic,实现您的目标会非常困难。

class MyGradientView : UIView 
    override class var layerClass : AnyClass  return CAGradientLayer.self 
    required init?(coder aDecoder: NSCoder) 
        super.init(coder:aDecoder)
        let lay = self.layer as! CAGradientLayer
        lay.type = .conic
        lay.startPoint = CGPoint(x:0.5,y:0.5)
        lay.endPoint = CGPoint(x:0.5,y:0)
        lay.colors = [UIColor.green.cgColor, UIColor.red.cgColor]
    
    override func layoutSubviews() 
        super.layoutSubviews()
        let shape = CAShapeLayer()
        shape.frame = self.bounds
        shape.strokeColor = UIColor.black.cgColor
        shape.fillColor = UIColor.clear.cgColor
        let b = UIBezierPath(ovalIn: shape.frame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)))
        shape.path = b.cgPath
        shape.lineWidth = 10
        shape.lineCap = .round
        shape.strokeStart = 0.1
        shape.strokeEnd = 0.9
        shape.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        shape.transform = CATransform3DMakeRotation(-.pi/2, 0, 0, 1)
        self.layer.mask = shape
    

【讨论】:

太奇怪了,我试过了,我的看起来超级奇怪。我一定是在做些不对劲的事情。很高兴指出它有帮助!在任何情况下都不能与我的 min SDK 一起使用。我想我会将您的答案标记为正确,因为继续前进它可能会帮助很多人 @user1366911 添加了代码以向您展示如何使用圆锥渐变。 @MarkusWMahlberg 为什么要回来讨论这个?你在浪费这个用户的时间和模组时间。我们现在正在清理标志。一开始就是你的错误。不要因为不想和你交往而辱骂对方。这是我第二次回到这个帖子。【参考方案2】:

iOS 12 上的任何人都应该听从 Matt 的建议,或者按照 DonMag 的建议使用 SFProgressCircle。

我的解决方案: 我个人最终添加了两个 CAShapeLayer,每个都有一个对应的 CAGradientLayer。

通过以编程方式将滑块分成两半,如下图所示,我能够在每一侧应用从上到下的渐变,从而得到我正在寻找的效果。它对用户是不可见的。

【讨论】:

以上是关于如何使 CAGradientLayer 遵循 CGPath的主要内容,如果未能解决你的问题,请参考以下文章

圆形 CAGradientLayer 蒙版

iOS 编程中, 如何使用 Swift 和 CAGradientLayer 绘制这个矩形

CG游戏原画造型教程

如何切换 CAGradientLayer?

如何使用 CAGradientLayer 绘制渐变色轮?

如何增加色彩空间CAGradientLayer