问题描述
要将渐变应用于NSView,最好使类继承自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)
}
}
(让我知道是否有更好/更简便的方法...)
效果很好,但现在我要发送自定义的颜色和色标集合。注意:*使用上述方法,我仅限于定义两个(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 ($0.color,$0.stop)})
)
那么如何向上述类发送许多自定义颜色和位置(或者希望有更好的建议)以创建自定义渐变(然后将其绘制在我的NSView上)?
解决方法
使用上述方法,我只能定义两个(startColor&startPosition和endColor&endPosition)。
不,您不是。这是一个可变参数。您可以根据需要添加任意数量的元组。效果很好:
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语言缺少此功能(“拼写”)。在Swift中调用可变参数的唯一方法是可变参数。
可用于提供颜色和停止位置的数组的初始化程序是init(colors:atLocations:colorSpace:)
。因此,如果您要提供此内容,请调用该初始化程序。
使用哑光的线索,我替换了let行(使用更合适的API init(colors:atLocations:colorSpace:)
):
let bgGradient = NSGradient(colorsAndLocations: (startColor,endPosition))
使用
let bgGradient = NSGradient(colors: colorStopArray.map { $0.color },atLocations: colorStopArray.map { $0.stop },colorSpace: NSColorSpace.genericRGB)
现在它可以按我的意愿工作。