- 设计系统
- 前端
- 开发工具
- UI组件
【免费下载链接】Lona
A tool for defining design systems and using them to generate cross-platform UI code, Sketch files, and other artifacts.
本篇技术指南围绕 Lona 设计系统工作区中的gradients.json文件展开,系统讲解渐变(Gradient)定义文件的 JSON 结构、字段语义、colorStops色标规则及其在 Lona Studio 与代码生成中的实际作用。读者将掌握如何编写一份可被 Lona Studio 正确识别、可在组件中以backgroundGradient引用的渐变定义文件,并通过仓库源码理解其解析与渲染的底层机制。
文件定位:设计系统渐变令牌的单一事实来源
在 Lona 中,设计系统(Design System)由工作区(Workspace)根目录下若干固定命名的 JSON 文件共同描述,gradients.json是其中之一。依据 docs/file-formats/README.md 的说明,这些设计系统文件各自存放在相对于工作区的固定位置:
| 类型 | 文件名 |
|---|---|
| 颜色 Colors | colors.json |
| 文本样式 Text Styles | textStyles.json |
| 渐变 Gradients | gradients.json |
| 阴影 Shadows | shadows.json |
| 类型 Types | types.json |
gradients.json的作用是"定义设计系统的渐变",即把产品中所有可复用的渐变统一收敛到一个文件里,作为渐变令牌(gradient token)的单一事实来源(single source of truth)。在 studio/LonaStudio/Module/LonaModule.swift 中可以看到,Lona Studio 通过FileSearch.search(filesIn:withSuffix:)递归扫描工作区中以gradients.json结尾的文件,并把首个命中的文件作为当前工作区的渐变来源:
var gradientsFileUrls: [URL] { return FileSearch.search(filesIn: url, withSuffix: "gradients.json") }而在 studio/LonaStudio/Preferences/CSGradients.swift 中,若工作区内找不到任何gradients.json,则回退到工作区根目录下的默认路径:
static var url: URL { return LonaModule.current.gradientsFileUrls.first ?? CSUserPreferences.workspaceURL.appendingPathComponent("gradients.json") }因此,一份可被识别的渐变文件必须位于工作区(或其子目录)内,且命名为gradients.json。缺少该文件时,Lona Studio 的渐变色选择器中不会出现任何渐变项(与colors.json、textStyles.json等文件的行为一致,参见 studio/README.md)。
文件规范:顶层结构与字段说明
依据 docs/file-formats/gradients.md,gradients.json的顶层是一个对象,其中包含一个名为"gradients"的数组。数组中的每一个渐变对象支持以下属性:
| 属性 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
id | string | 是 | 渐变的唯一标识。它会被 Lona Studio 内部使用,并出现在生成的代码中。因此它必须是"代码友好"(code-friendly)的:不能包含空格或非常用字符,因为它会被用作变量名。 |
name | string | 是 | 渐变的人类可读名称。它只显示在 Lona Studio 界面中,不会出现在生成的代码里。 |
comment | string | 否 | 渐变的可选说明文字,用于解释上下文信息(例如应如何使用该渐变)。它可能显示在 Lona Studio 界面中,但不会出现在生成的代码里。 |
colorStops | Array<{ position: number, color: Color }> | 是 | 渐变的色标(stops)列表。 |
字段语义要点
id决定代码标识符:由于id会直接作为变量名进入生成代码,命名时应遵循目标语言的标识符规则。从文档表述看,建议使用小驼峰或下划线风格(如gradient1、primaryBackgroundGradient),避免空格、连字符、中文字符等非常用字符,防止生成目标语言(Swift / JavaScript 等)时产生非法变量名。name仅供界面展示:name与id分离的设计,使代码标识与展示文案解耦——界面可以显示任意可读名称,而代码中使用稳定的id。comment是纯文档性字段:仅用于维护者之间的上下文说明,与colors.json中comment的语义一致(参见 docs/file-formats/colors.md)。colorStops中的color属于Color类型:Color类型既可以引用colors.json中已定义的颜色的id(推荐,保证单一事实来源),也可以内联书写 CSS 颜色值。colors.json文档明确指出:颜色"也可以内联出现在其他文件中(直接给出 CSS 颜色值),但对于'black'、'white'、'transparent'之外的颜色的内联写法并不推荐"(参见 docs/file-formats/colors.md)。合法的 CSS 颜色值示例包括:blue、fce、#ffccee、rgb(0,0,100)、rgba(255,255,255,0.3)。position为归一化位置:position取值为数字,表示该色标在渐变中的相对位置,通常落在0(起点)到1(终点)区间。
完整示例文件
以下是最小可用的gradients.json示例(来自原文档,可直接复制使用):
{ "gradients": [ { "id": "gradient1", "name": "Gradient 1", "colorStops": [ { "position": 0, "color": "black" }, { "position": 1, "color": "white" } ] } ] }该示例定义了一个从position: 0的黑色过渡到position: 1的白色的渐变。结合前文字段说明,可以在此基础之上扩展出更完整的实践写法:
{ "gradients": [ { "id": "gradient1", "name": "Gradient 1", "comment": "主界面顶部横幅使用的黑到白渐变", "colorStops": [ { "position": 0, "color": "black" }, { "position": 1, "color": "white" } ] }, { "id": "brandBackgroundGradient", "name": "品牌背景渐变", "comment": "引用 colors.json 中定义的颜色 id,保持单一事实来源", "colorStops": [ { "position": 0, "color": "lonaTeal" }, { "position": 0.5, "color": "#000080" }, { "position": 1, "color": "transparent" } ] } ] }注意:第二个示例中的
lonaTeal需在colors.json中定义(参见 docs/file-formats/colors.md 中的示例),否则解析器会将其按默认色处理(详见下文"源码级解析")。
源码级解析:Lona Studio 如何读取 gradients.json
原文档给出了格式规范,而仓库中的 studio/LonaStudio/Preferences/CSGradients.swift 提供了这份规范在 Lona Studio 中的真实实现,二者可以相互印证。
数据模型 CSGradient
解析结果被建模为CSGradient结构体,其核心字段与 JSON 属性一一对应:
struct CSGradient { let id: String? let name: String let colors: [CGColor] let locations: [NSNumber] var caGradientLayer: CAGradientLayer { let gradientLayer = CAGradientLayer() gradientLayer.colors = colors gradientLayer.locations = locations return gradientLayer } }值得注意的实现细节:
colorStops数组在解析时被拆解为两个平行数组:colors(CGColor 列表)与locations(NSNumber 位置列表),这正是 Core Animation 的CAGradientLayer所接受的输入形式(colors与locations属性)。caGradientLayer计算属性直接基于解析结果构建CAGradientLayer,说明渐变定义最终在 Lona Studio 内部通过 Core Animation 图层来渲染与预览。
解析逻辑 parse
CSGradients.parse是解析核心,其行为与原文档规范逐条对应:
private static func parse(_ data: CSData) -> [CSGradient] { guard let colorData = data["gradients"] else { return [] } return colorData.arrayValue.map({ gradient in let id = gradient["id"]?.string let name = gradient["name"]?.string ?? "No name" let pairs: [(CGColor, NSNumber)] = (gradient["colorStops"] ?? CSData.Null).arrayValue.map({ colorStop in let location = colorStop["position"]?.number ?? 0 let colorString = colorStop["color"]?.string ?? "transparent" let color = CSColors.parse(css: colorString, withDefault: NSColor.clear) return (color.color.cgColor, NSNumber(value: location)) }) let locations = pairs.map({ $0.1 }) let colors = pairs.map({ $0.0 }) return CSGradient(id: id, name: name, colors: colors, locations: locations) }) }从源码可以确认以下实现事实:
- 顶层键名:解析器只读取
data["gradients"],若顶层缺少"gradients"键则直接返回空数组,不会抛错。 name可缺省:虽然规范将name标记为必填,但解析器对缺失的name回退为字符串"No name",说明解析层面具备容错能力。position可缺省:colorStop["position"]?.number ?? 0表明缺失的position默认取0。color可缺省:缺失的color默认取"transparent"。- 颜色解析策略:每个色标的颜色字符串通过
CSColors.parse(css:withDefault:)处理。查看 studio/LonaStudio/Preferences/CSColors.swift 可知其解析流程为:先在colors.json中按id查找同名颜色(大小写不敏感比较),找到则使用该颜色的值;否则尝试按 CSS 字符串解析;两者都失败时使用默认色NSColor.clear。这印证了前文"color字段既支持colors.json的id引用、也支持内联 CSS 值"的规范说明,并揭示了内联 CSS 之外、通过id引用颜色时遵循"按 id 查找 → 按 CSS 解析 → 回退默认色"的三级解析顺序。
加载、重载与保存机制
CSGradients遵循CSPreferencesFile协议(定义于 studio/LonaStudio/Preferences/CSPreferences.swift),协议规定了save()、load()、reload()等能力。其中:
load()从文件路径读取 JSON;文件不存在时返回空对象,解析结果即为空数组,不会导致崩溃;data属性带有didSet观察器,文件内容变化时自动触发重新解析;reload()在切换工作区或配置变化时被调用。
具体到渐变,重载的触发点有两处:
- 工作区切换时:
CSWorkspacePreferences.reloadAllConfigurationFiles()会依次重载CSColors、CSTypography、CSGradients、CSShadows等全部设计系统配置文件(参见 studio/LonaStudio/Preferences/CSWorkspacePreferences.swift); - 应用启动时:
AppDelegate中调用CSGradients.reload()(参见 studio/LonaStudio/AppDelegate.swift)。
此外,CSGradients.gradient(withId:)提供了按id查找渐变的查询接口(studio/LonaStudio/Preferences/CSGradients.swift):
static func gradient(withId id: String) -> CSGradient? { return gradients.first(where: { $0.id == id }) }这正是id作为"内部使用标识"的体现:界面与代码生成均通过id而非name来定位渐变。
渐变在组件中的使用:backgroundGradient 参数
渐变定义文件本身并不直接决定某个视图的样式,它需要通过组件图层参数被引用。在 Lona Studio 的图层模型中,图层支持backgroundGradient参数,其类型为String?(studio/LonaStudio/Models/CSLayer.swift):
var backgroundGradient: String? { get { return parameters["backgroundGradient"]?.string } set { parameters["backgroundGradient"] = newValue?.toData() } }也就是说,在.component文件中,图层的backgroundGradient参数值就是gradients.json中某个渐变的id(或其表达式)。Lona Studio 的属性检查器(Inspector)中同样提供了backgroundGradient输入框,用于为图层绑定渐变(参见 studio/LonaStudio/Workspace/InspectorView/CoreComponentInspectorView.swift 的属性枚举与 第615行 的绑定逻辑)。
这构成了一个完整的数据流:gradients.json定义渐变令牌 → Lona Studio 解析为CSGradient→ 组件图层通过backgroundGradient参数按id引用 → 渲染预览时经caGradientLayer转为CAGradientLayer显示。
常见问题与最佳实践
结合规范与源码实现,整理以下实践建议:
id保持代码友好:id会进入生成代码成为变量名,务必使用字母、数字、下划线的组合,并保证全局唯一;修改id会导致所有引用该渐变的地方失效,因此发布后应保持稳定。- 优先引用
colors.json中的颜色 id:colorStops的color字段推荐使用colors.json中定义的颜色id(如lonaTeal),这样颜色值只维护一处;只有black、white、transparent这类基础色适合直接内联。 position使用归一化区间:通常取0.0~1.0;解析器对缺失position的默认值为0,多个色标位置相同时会退化为纯色效果,编写时应注意避免。- 利用
comment记录设计上下文:例如"用于按钮按下态的背景",便于设计系统维护者理解渐变用途;它不会污染生成代码。 - 文件命名与放置:文件必须命名为
gradients.json并位于工作区内(根目录或子目录均可,Lona Studio 会递归搜索并取首个命中文件);缺失该文件不会报错,但渐变选择器将为空。
小结
gradients.json是 Lona 设计系统工作区中的渐变令牌文件,其格式规范定义于 docs/file-formats/gradients.md:顶层为包含"gradients"数组的对象,每个渐变由代码友好的id、界面展示用的name、可选comment与必填的colorStops色标列表构成。仓库源码(CSGradients.swift)验证了该规范的实现细节,包括颜色按 id 引用与 CSS 内联解析、位置与颜色缺省值、CAGradientLayer渲染转换,以及组件图层通过backgroundGradient参数按id引用渐变的完整链路。掌握这份格式,即可为 Lona 工作区添加可复用的渐变设计令牌,并让它们在组件编辑与跨平台代码生成中保持一致。
- 设计系统
- 前端
- 开发工具
- UI组件
【免费下载链接】Lona
A tool for defining design systems and using them to generate cross-platform UI code, Sketch files, and other artifacts.
相关推荐
KernelSU 安装实战指南:LKM 与 GKI 双模式、KMI 匹配原理与 ksud boot-patch 详解
KernelSU 安装实战指南:LKM 与 GKI 双模式、KMI 匹配原理与 ksud boot patch 详解 本文基于 KernelSU 官方安装文档(
设计系统前端开发工具UI组件DINOv2-small模型安全部署指南:保护视觉AI应用的隐私与安全
DINOv2 small模型安全部署指南:保护视觉AI应用的隐私与安全 DINOv2 small是一款高效的视觉AI模型,在部署过程中确保其安全性至关重要。本指
laf WebIDE代码格式化:自定义代码风格与规范
laf WebIDE代码格式化:自定义代码风格与规范 你还在为团队代码风格混乱而头疼?还在手动调整缩进和空格?本文将带你全面掌握laf WebIDE的代码格式化
后端Serverless前端云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考