【问题标题】:How to fill a bezier path with gradient color如何用渐变颜色填充贝塞尔路径
【发布时间】:2017-05-17 04:41:11
【问题描述】:

我的自定义 UIView draw(_ rect: CGRect) 函数中有一个 UIBezierPath。我想用渐变色填充路径。请任何人指导我该怎么做。

我需要用渐变色填充剪辑,然后用黑色描边路径。

SO 中有一些帖子没有解决问题。例如Swift: Gradient along a bezier path (using CALayers),这篇文章将指导如何在UIView 中而不是UIBezierPath 中的图层上绘图。

注意:我正在开发 Swift-3

【问题讨论】:

标签: ios uiview swift3 core-graphics draw


【解决方案1】:

要回答你的这个问题,

我的自定义 UIView draw(_ rect: CGRect) 中有一个 UIBezierPath 功能。我想用渐变色填充路径。

假设您有一条椭圆形路径,

let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))

要创建渐变,

let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.magenta.cgColor, UIColor.cyan.cgColor]

我们需要一个渐变的遮罩层,

let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath

现在将此shapeLayer 设置为gradient 层的mask,并将其作为subLayer 添加到view 的层中

gradient.mask = shapeMask
yourCustomView.layer.addSublayer(gradient)

更新 创建一个带有描边的基础层,并在创建渐变层之前添加。

let shape = CAShapeLayer()
shape.path = path.cgPath
shape.lineWidth = 2.0
shape.strokeColor = UIColor.black.cgColor
self.view.layer.addSublayer(shape)

let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.magenta.cgColor, UIColor.cyan.cgColor]

let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
gradient.mask = shapeMask

self.view.layer.addSublayer(gradient)

【讨论】:

  • 感谢您的解决方案。渐变有效,但未显示笔画。 I need to fill the clip with a gradient color and then stroke the path with black color。我该如何解决这个问题。
  • 当我覆盖UIView 时,在draw() func 中我假设您的意思是self.layer 而不是self.view.layer。我遵循您所有更新的说明,工作非常接近,但它只显示黑色边界。图表中间没有显示任何笔划。 @马特
  • 感谢您的回答。我刚刚加了shape.fillColor = UIColor.clear.cgColor,问题就解决了。
  • 你也可以帮忙写那个帖子吗,stackoverflow.com/q/41464101/1084174
  • 甜蜜而简单。 :)
【解决方案2】:

您可以直接在 Core Graphics 中执行此操作,而无需使用 CALayer 类。使用bezierPath.addClip() 将贝塞尔路径设置为剪切区域。任何后续绘图命令都将被屏蔽到该区域。

我在我的一个项目中使用了这个包装函数:

func drawLinearGradient(inside path:UIBezierPath, start:CGPoint, end:CGPoint, colors:[UIColor])
{
    guard let ctx = UIGraphicsGetCurrentContext() else { return }

    ctx.saveGState()
    defer { ctx.restoreGState() } // clean up graphics state changes when the method returns

    path.addClip() // use the path as the clipping region

    let cgColors = colors.map({ $0.cgColor })
    guard let gradient = CGGradient(colorsSpace: nil, colors: cgColors as CFArray, locations: nil)
        else { return }

    ctx.drawLinearGradient(gradient, start: start, end: end, options: [])
}

【讨论】:

  • 如果从UIGraphicsBeginImageContext(:)而不是UIView开始,它不仅有用,而且很有必要。
猜你喜欢
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多