文 / 郁结
在做“智能设计” DSM 平台,DSM 是定义 C 端的设计规范、设计审查、自动生成设计稿的平台。
第一步呢,就是从一份 sketch 文件中,提炼一些“规范库”(包括 颜色、字号、字重)的内容。
(智能设计 - 相关内容定义)
颜色组件:就是可以复用的颜色,可以在“外观”里(参考位置下方截图的绿框)选择和新建
(如果找不到,可以选中一个颜色块,就会展示了)
字体组件:同上,也是可以复用的字体样式,在“外观”(下方绿色框)中选择和新建
(如果找不到,可以选中一个字体内容,就会展示了)
解题思路:
我查了查轮子,没查到特别好用的(可能是我搜索的姿势不对),下面是我搜的轮子~
大家如果查到好用的,也可以推荐给我~
imgcook 有没有相关的API
操作:人工询问&代码查看
结果:目前只针对了sketch画板做了一定的解析,没有针对颜色和字体的提取API。
sketch to html
介绍:从 sketch 转换成 html,已无更新。
地址:https://github.com/yu-tou/sketch-to-html
结果:没有找到针对颜色和字体的提取API,部分代码思路可以参考
sketch-node-parser
介绍:Parse files from Sketch using pure NodeJS.(用nodejs 转换 sketch)
地址:GitHub - afiedler/sketch-node-parser: Parse files from Sketch using pure NodeJS
结果:没有找到针对颜色和字体的提取API,sketch文件结构解析可以参考
没办法了~ 看看文档自己写吧!找到的学习网站:sketch developer(英文原版网站)、(中文 较为落后,缺失内容)。
其实 .sketch 的文件是一个文件集合,改成 .zip 后缀后解压,就可以获取相关的文件。
拿 antd 官方的资源文档举例(我用的是绿框中的文件):
解压了上方下载的 AntDesign4.0-Light.sketch 文件后结构如下图:
介绍解压后相关的的文件:
(官方文档文件夹介绍)
对照找下官方对于文档(下方截图)的描述( 官方文档原文),认真阅读下,发现共享的数据会存储在document.json 文件中,只要解析document.json 文件就可以获取共享样式(shared styles)。共享样式:包括字体、颜色等。
打开这个43009行的文件,我懵了,整理下后,发现就是这些结构,然后我们需要的就是 layerStyles(颜色)、layerTextStyles(字体),下面为 document.json 的整个内容结构。
layerStyles
先说说颜色的结构,找到 object-value-fills-color 里的 rgba - red/green/blue/alpha ,具体layerStyles 的 json 截图如下:
如果还需要rgba 转换成 hex的色值,我刚好也做了,基本网上可以找到很多资料,但是实际测试下来,需要注意的重点是由于数值需要乘255的原因,会有小数的情况,所以使用 Math.round 来四舍五入取整。
直接 show code :
//rgba to hex function
function Rgba2hex(r, g, b, a) {
r = Math.round(r * 255);
g = Math.round(g * 255);
b = Math.round(b * 255);
r = r.toString(16);
g = g.toString(16);
b = b.toString(16);
a = Math.round(a * 255).toString(16);
if (r.length == 1) r = "0" + r;
if (g.length == 1) g = "0" + g;
if (b.length == 1) b = "0" + b;
if (a.length == 1) a = "0" + a;
return r + g + b + a;
}
layerTextStyles
字体的结构,按顺序找到 layerTextStyles - objects - value - textStyle - encodedAttributes
- MSAttributedStringFontAttribute - attributes 获取相关的数值,具体 json 如下:
写下代码思路(下面的流程图,大家可以放大查看):
show code 环节~
import * as JSZip from "jszip";
//二进制流 buffer 读取
function blobToBuffer(file: any) {
return new Promise((resolve) => {
let arrayBuffer;
const fileReader = new FileReader();
fileReader.onload = (event: any) => {
arrayBuffer = event?.target?.result;
resolve(arrayBuffer);
};
fileReader.readAsArrayBuffer(file);
});
}
// buffer 变成json 内容
async function zipFileToJSON(zipFile: any, fileName: any) {
const text = await zipFile[fileName].async("text");
const json = JSON.parse(text);
return json;
}
//解压 buffer 变成 files
async function unZipSketch(buffer: any) {
const zip = await JSZip.loadAsync(buffer);
return zip.files;
}
const getRenameAttr = async (file: any, getType: string) => {
//1.sketch 文件上传
//2.二进制流 buffer 读取
const buffer: any = await blobToBuffer(file);
//3.解压 buffer 变成 files
const zipFile = await unZipSketch(buffer);
//4.files 中找到 doucment.json ,从 buffer 变成json 内容
const docFile = await zipFileToJSON(zipFile, "document.json");
//5.解析 doucment.json , 获取 字体 和 颜色
let fontList: any = [];
//命名 字体 解析
const fontReferences = docFile?.layerTextStyles?.objects || [];
for (let index = 0; index < fontReferences.length; index++) {
const font = fontReferences[index];
const textStyle =
font?.value?.textStyle?.encodedAttributes
?.MSAttributedStringFontAttribute?.attributes;
const fontPush = {
name: font.name,
fontSize: textStyle?.size,
fontWeight: textStyle?.name,
};
fontList.push(fontPush);
}
//命名 颜色 解析
let colorList: any = [];
const colorReferences = docFile?.layerStyles?.objects || [];
for (let index = 0; index < colorReferences.length; index++) {
const color = colorReferences[index];
const fill = color?.value?.fills[0].color;
const { blue, green, red, alpha } = fill;
// console.log("fill", fill);
const colorPush = {
name: color.name,
value: Rgba2hex(red, green, blue, alpha),
};
colorList.push(colorPush);
}
let finalList: any = {};
if (colorList.length > 0) {
finalList.colorList = colorList;
}
if (fontList.length > 0) {
finalList.fontList = fontList;
}
return finalList;
};