AI 生成设计 Token:从品牌规范到代码变量的自动转换
AI 生成设计 Token:从品牌规范到代码变量的自动转换

一、设计 Token 的"手工翻译":从 Figma 到代码的断层
设计 Token 是设计系统的原子单位——颜色、字号、间距、圆角等视觉属性被抽象为命名变量,确保设计与代码的一致性。但品牌规范文档(PDF/Keynote)中的色值和字号,需要人工逐条翻译为 CSS 变量、Swift 常量和 Android 资源文件。一个包含 80 个颜色 Token、40 个间距 Token 和 30 个字号 Token 的设计系统,手工翻译需要 1-2 天,且每次品牌升级都需要重复这个过程。更致命的是,翻译过程中的手动复制粘贴极易引入错误——一个色值从 #3B82F6 误写为 #3B82E6,在视觉上几乎不可察觉,却导致品牌色不一致。
二、设计 Token 的体系结构与转换链路
2.1 从品牌规范到多平台 Token 的完整链路
flowchart TB
A[品牌规范文档<br/>PDF/图片] --> B[AI 解析提取]
B --> C[原始 Token 集<br/>JSON/DTCG 格式]
C --> D[语义映射<br/>primary/secondary/...]
D --> E[多平台转换]
E --> F[CSS Variables]
E --> G[Swift UIColor]
E --> H[Android XML]
E --> I[Flutter ThemeData]
E --> J[React Native]
subgraph AI解析模块
B1[视觉模型:提取色值/字号]
B2[文本模型:理解命名语义]
B3[规则引擎:校验一致性]
B1 --> B2 --> B3
end
A --> B1
2.2 DTCG 设计 Token 标准格式
import json
from dataclasses import dataclass, asdict
from typing import Any
@dataclass
class DesignToken:
"""符合 DTCG (Design Tokens Community Group) 规范的 Token 定义"""
value: Any
type: str # color, dimension, fontFamily, ...
description: str = ""
extensions: dict = None
def create_token_set() -> dict:
"""创建符合 DTCG 规范的 Token 集"""
return {
"color": {
"brand": {
"primary": DesignToken(
value="#3B82F6",
type="color",
description="品牌主色,用于主要按钮和链接",
),
"secondary": DesignToken(
value="#10B981",
type="color",
description="品牌辅色,用于成功状态和辅助操作",
),
},
"neutral": {
"50": DesignToken(value="#FAFAFA", type="color"),
"100": DesignToken(value="#F5F5F5", type="color"),
"900": DesignToken(value="#171717", type="color"),
},
},
"dimension": {
"spacing": {
"xs": DesignToken(value="4px", type="dimension"),
"sm": DesignToken(value="8px", type="dimension"),
"md": DesignToken(value="16px", type="dimension"),
"lg": DesignToken(value="24px", type="dimension"),
},
"radius": {
"sm": DesignToken(value="4px", type="dimension"),
"md": DesignToken(value="8px", type="dimension"),
"lg": DesignToken(value="16px", type="dimension"),
},
},
}
三、AI 驱动的 Token 自动生成方案
3.1 品牌规范文档解析
class BrandDocParser:
"""从品牌规范文档中提取设计 Token"""
def __init__(self, vision_client, llm_client):
self.vision = vision_client
self.llm = llm_client
def parse_brand_pdf(self, pdf_path: str) -> dict:
"""解析品牌规范 PDF,提取色值、字号、间距等 Token"""
# 1. 将 PDF 转为图片逐页分析
pages = self._pdf_to_images(pdf_path)
all_tokens = {}
for page_img in pages:
# 2. 视觉模型提取色板和字号信息
visual_info = self.vision.analyze(
page_img,
prompt="提取此品牌规范页面中的所有色值(HEX格式)、字号(px/pt)和间距值。"
"输出JSON格式:{colors: [{name, hex}], fonts: [{name, size}], spacing: [{name, value}]}"
)
# 3. LLM 语义化命名
named_tokens = self._assign_semantic_names(visual_info)
all_tokens.update(named_tokens)
return all_tokens
def _assign_semantic_names(self, raw_tokens: dict) -> dict:
"""使用 LLM 为提取的原始值分配语义化名称"""
prompt = f"""为以下设计属性分配语义化 Token 名称。
原始色值: {raw_tokens.get('colors', [])}
原始字号: {raw_tokens.get('fonts', [])}
原始间距: {raw_tokens.get('spacing', [])}
命名规范:
- 颜色:使用 语义.变体 格式,如 brand.primary, neutral.100, semantic.error
- 字号:使用 用途.层级 格式,如 text.heading.lg, text.body.md
- 间距:使用 尺寸等级 格式,如 spacing.xs, spacing.md
输出 DTCG 兼容的 JSON 格式。"""
response = self.llm.chat(prompt)
return json.loads(response)
3.2 多平台 Token 转换引擎
class TokenTransformer:
"""将 DTCG Token 转换为各平台代码格式"""
def to_css_variables(self, tokens: dict) -> str:
"""转换为 CSS 自定义属性"""
lines = [":root {"]
self._flatten_tokens(tokens, lines, prefix="")
lines.append("}")
return "\n".join(lines)
def _flatten_tokens(self, obj: dict, lines: list, prefix: str):
"""递归展平 Token 树为 CSS 变量"""
for key, value in obj.items():
var_name = f"{prefix}-{key}" if prefix else f"--{key}"
if isinstance(value, dict) and 'value' in value:
# 叶子节点:Token 定义
css_value = self._to_css_value(value['value'], value['type'])
lines.append(f" {var_name}: {css_value};")
elif isinstance(value, dict):
# 分支节点:递归
self._flatten_tokens(value, lines, var_name)
def _to_css_value(self, value: str, token_type: str) -> str:
"""将 Token 值转换为 CSS 合法值"""
if token_type == "color":
return value # HEX 值直接使用
elif token_type == "dimension":
return value # px 值直接使用
return value
def to_swift(self, tokens: dict) -> str:
"""转换为 Swift UIColor 扩展"""
lines = ["import UIKit", "", "extension UIColor {"]
colors = self._extract_by_type(tokens, "color")
for name, value in colors.items():
swift_name = name.replace("-", "").replace(".", "_").lower()
r, g, b = self._hex_to_rgb(value)
lines.append(
f" static let {swift_name} = UIColor("
f"red: {r/255:.3f}, green: {g/255:.3f}, blue: {b/255:.3f}, alpha: 1.0)"
)
lines.append("}")
return "\n".join(lines)
def to_android_xml(self, tokens: dict) -> str:
"""转换为 Android colors.xml"""
lines = ['<?xml version="1.0" encoding="utf-8"?>', '<resources>']
colors = self._extract_by_type(tokens, "color")
for name, value in colors.items():
android_name = name.replace("-", "_").replace(".", "_").lower()
lines.append(f' <color name="{android_name}">{value}</color>')
lines.append('</resources>')
return "\n".join(lines)
def _extract_by_type(self, tokens: dict, target_type: str) -> dict:
"""按类型提取所有 Token"""
result = {}
for key, value in tokens.items():
if isinstance(value, dict):
if 'type' in value and value['type'] == target_type:
result[key] = value['value']
else:
result.update(self._extract_by_type(value, target_type))
return result
@staticmethod
def _hex_to_rgb(hex_color: str) -> tuple:
hex_color = hex_color.lstrip('#')
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
3.3 一致性校验与自动修复
class TokenConsistencyChecker:
"""校验 Token 集的一致性和完整性"""
def check(self, tokens: dict) -> list:
issues = []
# 1. 检查色值间距是否均匀(中性色梯度)
neutral_colors = self._get_neutral_scale(tokens)
if neutral_colors:
lightness_values = [self._perceived_lightness(c) for c in neutral_colors]
diffs = [lightness_values[i+1] - lightness_values[i]
for i in range(len(lightness_values) - 1)]
if max(diffs) / (min(diffs) + 1e-8) > 2.0:
issues.append({
'type': 'UNEQUAL_SPACING',
'message': '中性色梯度间距不均匀,建议调整明度分布',
'detail': f'最大间距差: {max(diffs):.1f}, 最小: {min(diffs):.1f}',
})
# 2. 检查语义色是否有对应的暗色变体
semantic_colors = self._get_semantic_colors(tokens)
for name, value in semantic_colors.items():
dark_name = name.replace('light', 'dark')
if dark_name not in semantic_colors:
issues.append({
'type': 'MISSING_DARK_VARIANT',
'message': f'语义色 {name} 缺少暗色变体',
})
# 3. 检查字号是否形成合理的模块化比例
font_sizes = self._get_font_sizes(tokens)
if font_sizes:
ratios = [font_sizes[i+1] / font_sizes[i]
for i in range(len(font_sizes) - 1)]
if any(r < 1.1 or r > 1.5 for r in ratios):
issues.append({
'type': 'IRREGULAR_TYPE_SCALE',
'message': '字号比例不一致,建议使用 1.2-1.333 的模块化比例',
})
return issues
@staticmethod
def _perceived_lightness(hex_color: str) -> float:
r, g, b = [int(hex_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4)]
return 0.299 * r + 0.587 * g + 0.114 * b
四、边界分析与架构权衡
4.1 视觉模型提取的精度限制
品牌规范 PDF 中的色值可能以 CMYK 格式标注,视觉模型从截图中提取的 RGB 值与原始 CMYK 值存在色域转换偏差。关键品牌色应从源文件(Figma/Sketch)直接导出,视觉模型仅用于辅助提取和校验。
4.2 语义命名的歧义性
同一色值在不同上下文中可能有不同语义——#EF4444 既是"错误红"也是"促销红"。LLM 的语义命名依赖上下文理解,可能产生不符合团队约定的命名。需要提供命名规范作为约束条件,并在生成后由设计师审核。
4.3 多平台格式差异
CSS 变量支持运行时动态切换(暗色模式),Swift 和 Android 的颜色资源是编译时常量。跨平台 Token 转换时,需要为支持动态切换的平台生成额外的主题变体文件,这增加了维护复杂度。
4.4 版本同步问题
设计 Token 在 Figma 中更新后,代码中的 Token 可能未同步更新,导致设计与实现不一致。需要建立 Figma Plugin → Token 文件 → 代码的自动化同步管线,而非依赖人工同步。
五、总结
AI 生成设计 Token 的核心价值在于将品牌规范文档到代码变量的"手工翻译"自动化。视觉模型从品牌文档提取色值和字号,LLM 分配语义化命名,转换引擎输出多平台代码格式,一致性校验器检测间距不均匀、暗色变体缺失和字号比例失调等问题。工程实践中需注意视觉提取的精度限制、语义命名的歧义性、多平台格式差异和版本同步问题。AI 生成最适合作为 Token 初始化和批量更新的加速工具,关键品牌色的准确性仍需设计师确认。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)