如何在 swift 中存储 NSGradient(colorsAndLocations:) 的元组

How store a tuple for NSGradient(colorsAndLocations:) in swift

要将渐变应用于 NSView,似乎最好制作一个 class 从 NSView 继承并覆盖设置路径和绘制渐变的 draw 方法。

class GradientView: NSView {

var startColor = NSColor.red
var startPosition: CGFloat = 0
var endColor = NSColor.white
var endPosition: CGFloat = 1
var rotation: CGFloat = 0


override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    let bgGradient = NSGradient(colorsAndLocations: (startColor, startPosition), (endColor, endPosition))
    let path = NSBezierPath.init(rect: self.bounds)
    bgGradient?.draw(in: path, angle: rotation)
}
}

(让我知道是否有 better/easier 方法...)

效果很好,但现在我想发送一组自定义的颜色和色标。注意:*使用上述方法,我仅限于定义两个(startColor & startPosition 和 endColor & endPosition)。

我想使用(一个数组?)元组(包含多种颜色及其停止值)。设置颜色和位置的 API 是 NSGradient(colorsAndLocations:) 并使用元组 (NSColor, CGFloat).

我可以添加一个像 var colorStopArray: [(color: NSColor, stop: CGFloat)] = [] 这样的参数来创建一个(这样的)元组数组。我也可以附加值:colorStopArray.append((startColor, startPosition)).

但是我怎样才能将它分配给 API?

我尝试了很多方法,但它们都会导致错误(例如,尝试 NSGradient(colorsAndLocations: colorStopArray.flatMap{return ([=15=].color, [=15=].stop)})

那么如何将许多自定义颜色+位置发送到上面的 class(或者希望是更好的建议)来创建自定义渐变(然后将在我的 NSView 上绘制)?

With this above method, I am limited to defining two (the startColor & startPosition and endColor & endPosition) only.

不,你不是。这是一个可变参数;您可以根据需要添加任意数量的元组。这很好用:

let startColor = NSColor.red
let startPosition: CGFloat = 0
let middleColor = NSColor.blue
let middlePosition: CGFloat = 0.5
var endColor = NSColor.white
var endPosition: CGFloat = 1
let bgGradient = NSGradient(colorsAndLocations: 
    (startColor, startPosition), 
    (middleColor, middlePosition), 
    (endColor, endPosition))

如果问题是“我可以将数组转换为可变参数吗?”,那么很遗憾,答案是否定的。 Swift 语言缺少此功能(“splatting”)。在 Swift 中调用可变参数的唯一方法是作为可变参数。

可让您提供一组颜色和停止位置的初始化程序是 init(colors:atLocations:colorSpace:)。因此,如果这是您想要提供的,请改为调用该初始化程序。

利用马特的线索,我替换了 let 行(使用更合适的 API init(colors:atLocations:colorSpace:)):

let bgGradient = NSGradient(colorsAndLocations: (startColor, startPosition), (endColor, endPosition))

let bgGradient = NSGradient(colors: colorStopArray.map { [=11=].color }, atLocations: colorStopArray.map { [=11=].stop }, colorSpace: NSColorSpace.genericRGB)

现在它的功能如我所愿。