
sunilwang
2023/03/22阅读:47主题:绿意
Psd设计稿解析之路
伟大的马老师曾经说过,生产工具是生产力的决定因素之一。实际工作中,一个好用的工具确实可以有效提升开发效率。
起源
一次和设计同学的闲聊中,了解到他们的设计稿交付时,大多数都是基于sketch,而Psd的设计稿非常少,使得他们一身Psd技艺无用武之地。究其原因,是因为sketch对css样式支持度较高,转换到HTML元素相对容易,但Psd并无一一映射规则,且Psd的样式繁杂,解析起来相当麻烦。 鲁迅先生说过:“即使艰难,也还要做;愈艰难,就愈要做”。打了一番鸡血,几位小伙伴一拍即合,便开始去做这件“艰难”的事情——将Psd设计稿转译成HTML。
调研
目前市面上可用的转换插件以这两种为主,具体特点分析如下:
解析插件名称 | psd.js | ag-psd |
---|---|---|
解析依据 | psd.rb解析器 | photoshop官方文档 |
star数 | 2.5k | 297 |
更新频率 | 去年 | 上个月 |
issue回复速度 | 周甚至月 | 天级 |
图像模式支持度 | 深度和图像模式有限 | 几乎所有 |
遍历方式 | 插件API方法 | 自由操作原始数据 |
颜色模式 | rgba | rgba |
图片操作方式 | 转png | 支持canvas所有API |
转换css属性 | 属性有限 | 大量属性可转换 |
解析数据(以6.8MB的Psd文稿为例) | 135KB | 34.1MB |
解析成功率 | 重名图层会出现卡死/报错 | 100% |
结果一目了然,除star数稍逊色之外,其他方面ag-psd一骑绝尘,选定插件,开始搬砖。
架构设定
经过设计讨论,最终决定了解析的具体步骤,如下图所示。
图层分类
目前图层可分为三类:组(group),文字(text),图片(image)。其中组图层有children属性,它是可以包含所有类型图层的列表;文字图层也拥有children属性,但它仅能包含文字图层。
enum LayerShowType {
GROUP = 'group',
TEXT = 'text',
IMAGE = 'image',
}
样式转换
解析得到的是接近Psd源格式的数据,要想将其转换为HTML文件,首要任务是将Psd属性“翻译”成css样式。 但Psd的样式无法和css样式一一对应,需要做转换映射;而且同一文本框中,可能出现多种样式文字,针对于此,需要做文字样式拆离
转换映射
其中,常见的opacity(透明度),borderRadius(圆角),backgroundColor(背景色)等样式是通用样式,也很容易找到对应属性,但文字就相对难处理一些。 诸如删除线、下划线,加粗,倾斜等样式,Psd属性中是以Boolean形式存在;行高属性在Psd中是leading,单位是Psd文稿定义的单位;圆角在Psd中以Object存储,等等;而css样式中,是以单独样式及固定值存在,这里都需要转换映射。
样式拆离
如下图所示,2种不同的样式糅合在一个文本图层中,需要从图层的TextStyleRun列表中,将各自样式单独拆离出来,再做转换映射。
// Psd解析原始数据
"styleRuns": [
{
"length": 1,
"style": {
"fontSize": 24,
"autoKerning": false,
"fillColor": {
"r": 225.99885,
"g": 61.15665,
"b": 61.15665,
"a": 1
}
}
},
{
"length": 69,
"style": {
"fontSize": 24,
"autoKerning": true,
"fillColor": {
"r": 225.99885,
"g": 61.15665,
"b": 61.15665,
"a": 1
}
}
},
{
"length": 88,
"style": {
"fontSize": 48,
"autoKerning": true,
"fillColor": {
"r": 26.9994,
"g": 23.715,
"b": 23.715,
"a": 1
}
}
},
{
"length": 39,
"style": {
"fontSize": 36,
"autoKerning": true,
"fillColor": {
"r": 129.999,
"g": 46.39215,
"b": 46.39215,
"a": 1
}
}
}
]
定位处理
由于Psd源数据本身就是绝对定位,最简单高效的方式是沿用它。所以我们直接使用position: absolute
的样式,将图层属性top, right, bottom, left
直接转换。
图片处理
考虑到时间及转化难度的问题,目前的图片分为两部分:设计稿中本身的图片图层及非文字图层。由于ag-psd基于canvas处理图片,此处借用canvas的toDataURL方法,将所有图片统一转换成base64格式来存储备用。
HTML文件拼接
准备就绪,开始拼接HTML元素。但因为场景在node端,无法直接使用Document.createElement来创建DOM,更无法直接添加css样式。 几经寻找对比,终于找到一款在node端操作DOM的包——cheerio,它提供了在node端操作DOM的一套API,是jQuery的子集。有了它,何愁不能拼接完整的HTML,想到这里,不禁沾沾自喜。
拼接分为如下3个步骤:
1. 数据解析
利用上述结论,将原Psd数据进行解析转换,将图层类型转换成固定三类(组,文字,图片),同时将样式转换成对应图层类型的css属性。
2. 递归处理
对转换后的数据进行递归处理,使用 cheerio
的API,对 组(group) 图层,新建div元素;对 文字(text) 图层,新建p元素;对 图片(image) 图层,新建img元素。再通过attr及css方法把对应的css样式添加到DOM元素中。
3. 单位变换
本次解析是基于移动端设计稿处理,但由于移动端屏幕尺寸多种多样,px单位是无法在HTML中直接使用。考虑到大部分移动端设计稿是基于750px宽度来定义尺寸,此处均将px转换为rem单位,同时定义基准fontSize = 100px
。 由于单位转换后,文字样式的宽度会有一定差异性,会出现折行问题。经过多次尝试,基于rem单位,我们会给文字添加一定数值的宽度补偿
,最终展示的文字能够完美适配原设计稿。
let newWidth = (Math.ceil(width / 10) * 10 * ratio + 0.3) + unit;
结果展示
最终,我们得到了这样的结果:用户中心设计稿 😄,所幸还原度还不错,粗略估计在85%以上。
原设计稿:
转换后页面效果(在线设计稿地址 ):
未来规划
目前Psd设计稿的还原度并非最理想状态,同时仅还原出HTML也不是我们的目的。未来有如下的规划:
-
大幅提升设计稿的还原度 -
完成Psd在线设计稿功能开发,方便前端开发者使用
如何体验
进入毕加索官网,点击右上角 解析PSD
按钮即可体验Psd设计稿转换。 同时,也欢迎大家关注58开源项目 Picasso ,体验效果、改进代码、协作开发都可以提到issue中。
作者介绍
王明忠:天生的乐观派,而且永不止步
姜娜娜:踏实做好每一件事
作者介绍
