关于前端:设计稿UI视图自动生成代码方案的探索

3次阅读

共计 7056 个字符,预计需要花费 18 分钟才能阅读完成。

1 背景

设计稿(UI 视图)转代码是前端工程师日常一直反复的工作,这部分工作复杂度较低但工作占比拟高,所以晋升设计稿转代码的效率始终是前端工程师谋求的方向之一。此前,前端工程师尝试过将业务组件模块化构建成通用视图库,并通过拖拽、拼接等模式搭建业务模块,从而实现视图复用,升高设计稿转代码的研发老本。但随着业务的倒退和个性化的驱动,通用视图库无奈笼罩所有利用场景,本文提出了一种设计稿主动生成代码的计划。

目前,业内支流的代码生成计划有两种,一种是通过训练神经网络,从图片或草图间接生成代码,以微软 sketch2json 为代表;另一种是基于 Sketch 源文件,从中解析出图层信息转化成 DSL 并生成代码,以 imgCook 为代表。通过实际,咱们发现第一种计划基于神经网络的代码生成算法尽管简略粗犷,但简单层布局的准确率较低、可解释水平不高导致后续无奈继续优化。计划二中 Sketch 源文件信息量丰盛、算法自定义水平高、优化空间大。因而,咱们调研了业界基于 Sketch 的代码主动生成计划(已对外颁布或者开源),发现了一些有余并尝试解决,上面从算法准确率、代码可读性、研发流程覆盖度等方面做一下比照(该比照后果仅考查业界计划对咱们本人业务的适用性,理论后果可能存在差别):

  • 算法准确率方面:淘宝 imgCook 反对基于 AI 的组件辨认,不反对成组布局,准确率中等(从官网理解到能够辨认循环布局,但不能辨认出测试样本中的循环布局),58 Picasso 仅反对原始组件的辨认,简单组件生成谬误较多,不反对成组 / 悬浮 / 循环布局,准确率较低。
  • 代码可读性方面:淘宝 imgCook 在生成布局时,测试样本中图层重叠区域应用到了基于根布局的相对定位形式,不合乎 RD 预期,可读性个别,而咱们的计划应用绝对定位形式,可读性较好。
  • 研发流程覆盖度方面:淘宝 imgCook 从 RD 视角构建了一个 IDE,反对在 IDE 中实现款式调整、逻辑绑定;而咱们的计划从产研合作视角登程,反对数据、逻辑、埋点的可视化配置及上线。

2 计划介绍

如图所示,配置平台次要分成三块包含:设计稿转视图树(UI2DSL)、视图树转代码(DSL2Code)、以及业务信息绑定,上面简略介绍一下每一块的作用。

  • 设计稿转 DSL 视图树(UI2DSL):将设计稿转化成平台无关的 DSL 视图树。
  • 视图树转代码(DSL2Code):将 DSL 视图树转化成基于 Flex 布局的 MTFlexBox 动态代码。
  • 业务信息绑定:提供可视化配置工具,反对 MTFlexBox 动态代码绑定后盾数据、业务逻辑、以及曝光 / 点击等埋点逻辑。

2.1 设计稿转视图树(UI2DSL)

UI2DSL 次要经验以下四个步骤:

2.1.1 设计稿导入

在日常开发过程中,咱们接触比拟多的组件有按钮、题目、进度条、评分组件等,然而 Sketch 数据源中并没有这些组件只有图层信息,图层是设计师在设计 UI 视图时用到的视图控件。组件与图层的对应关系是一对多的关系,图层在 Sketch 数据源中的表现形式如下图中的 JSON 数据结构所示,形容了图层的坐标、大小等信息,后续布局生成就是基于对图层的切割来实现的。

[
    {
        "class_name":"MSTextLayer",
        "font_face":"PingFangSC-Medium",
        "font_size":13.44,
        "height":36.5,
        "index":8,
        "line_height":18.24,
        "name":"恒都民生精选猪小排带骨 400g±25g",
        "object_id":"EF55F482-A690-4EC2-8A6E-6E7D2C6A9D91",
        "opacity":0.9000000357627869,
        "text":"恒都民生精选猪小排带骨 400g±25g",
        "text_align":"left",
        "text_color":"#FF000000",
        "type":"text",
        "width":171.8,
        "x":164.2,
        "y":726.7
    },
    //......
]

2.1.2 组件辨认

从下面的数据源能够看出,图层有图片、文字、矩形等根本类型,在组件辨认这一步图层须要被转化成文字 / 图片 / 进度条 / 评分组件 / 价格组件 / 角标等日常开发应用的组件类型。然而目前咱们的停顿还停留在只能将图层辨认为文字或者图片的阶段,后续咱们将接入淘宝开源的 pipcook 框架,基于神经网络算法进行更加丰盛的组件类型辨认。

2.1.3 可视化干涉

设计稿作为输出源是设计稿主动转代码的根底,这对设计稿的设计规范要求较高。但在实践中,咱们发现设计师会利用 Sketch 中的根本图形(每个图形最终造成数据源中的一个图层)叠加来形容一个组件的视觉效果,因而设计稿中不可避免会呈现冗余图层的问题,烦扰 DSL 的生成。尽管咱们也尝试了利用自动化的伎俩删除冗余图层,但对于算法不能辨认的局部(例如:图片上有一个文本图层,然而理论状况中文本是显示在图片里的,这个时候无奈从算法层面决定是否删除文本),依然须要靠人工进行图层删除、合并等,否则无奈失常生成 DSL。设计稿次要有以下几类问题。

图层未合并

上图是从设计稿解析进去的后果,能够发现在“美团优选”文字上方的图片中有很多红色的矩形框(每个矩形框是一个独自的图层),而算法预期的输出是一个图层,因而须要在算法解决前将多个图层合并成一个图层,右侧的三张图也有相似问题。咱们与设计同学进行过沟通,设计同学示意违心在产出设计稿之前将图层进行合并,但因为目前无奈提供检测机制(图层合并是否有脱漏无奈自动检测进去),也就无奈彻底防止图层未合并的问题。

图层地位穿插

实际中发现当设计稿中不同字体 / 大小 / 色彩的文字排列在一起时,解析进去的图层信息往往会呈现重叠的状况,因为 DSL 视图树算法依赖地位来确定不同组件的束缚关系,因而地位的穿插会对算法准确度造成较大的影响。

简单背景图层

上图中红色背景是由 2 个图层(2 个蓝色矩形框)拼接造成的,左图上的蓝色图层是纯色,右图上的蓝色图层是渐变色,在两个图层未合并的状况下,算法生成的代码将会出错。

下面提出的问题,通过束缚设计师来达到设计稿的规范化,难度较大,所以咱们提供了可视化干涉工具。上面对上述问题做一个简略的总结:

  • 问题一:图层未合并问题肉眼很 容易辨认 进去,利用工具将冗余图层进行 疾速合并删除 即可。
  • 问题二:图层穿插问题肉眼不易辨认,因而咱们提供了 检测工具 ,基于检测工具能够对设计稿中的穿插问题 疾速修复
  • 问题三:简单背景问题肉眼不易辨认,临时也没有无效的检测工具,用户能够采纳 边干涉边生成 的形式生成 DSL。

可视化干涉是 UI2DSL 重要的一环,通过可视化干涉,将不规范的设计稿转化为规范的图层信息后再输出给算法,能够极大地晋升算法的准确率。这里咱们和 imgCook 的解决形式有一个区别:imgCook 在引入了阈值解决等算法后(更智能,出错概率更大),可视化干涉能力次要体现在预先,而咱们在生成 DSL 之前容许用户对图层进行干涉,在干涉时用户面对的是直观的图层信息,能够无效升高工具的应用门槛(更稳固,成果更好)。

2.1.4 视图树生成

将扁平的数据源转化为树状构造的 DSL,这个过程如果是人脑来做会怎么思考呢?先确定布局的整体构造是行布局或者列布局,而后再确定部分区域应该是什么布局构造,最初组装起来造成视图树。这个过程与递归算法相似,因而咱们采纳了递归算法作为算法的主框架,同时引入了“横竖切割 + 布局构造 + 模型评估”三大利器。

利器一:横竖切割

生成 DSL 时采纳了整分的思路,行将大布局一直的切分成小布局,上面以动画的模式看一下简化过的 DSL 生成过程:

将设计稿一部分区域视为一个子区域,最开始的时候子区域和整个模板的面积一样大,基于图层的地位、大小信息,计算每个图层的上 / 下 / 左 / 右边缘坐标与其余图层的绝对关系,就能够寻找到切割点(如上图中红色箭头所指的地位)。接下来根据切割点,将子区域切割成更小的子区域,在切割的过程中如果切割点是横向的,则生成列布局;如果切割点是纵向的,则生成行布局。通过一直的切割子区域失去更小的子区域,直到所有的子区域只剩下图片或者文本等不可切割的图层,这样就能够生成残缺的 DSL 视图树了。为了不便读者了解,图例中只演示了行布局、列布局的切分过程,理论状况还蕴含了其余布局类型,会要简单许多。

这里还要留神一个问题,当有 3 个切割点时,咱们抉择了间接将子区域切割成 4 个子区域,实际上咱们能够只抉择 1 个切割点进行切割,也能够抉择 2 个切割点进行切割,当有 N 个切割点时,实际上存在(N 的阶乘 +1)种切割形式,具体抉择哪种切割形式,咱们会在利器三中探讨。

利器二:布局构造

每个图层都是一个矩形,为了生成布局构造只能依赖矩形的上下左右坐标信息。因而,对布局构造进行分类时,咱们依据矩形与矩形之间的地位关系(相交、相离和蕴含关系)做了以下分类。

留神:从生成 DSL 的后果来看,蕴含布局 成组布局 的解决形式其实是一样的,都是应用相似于 FrameLayout 的层叠布局蕴含外部图层元素,然而咱们依然放弃分类准则(矩形之间的地位关系)不变。

上图中,相离、蕴含比拟好了解,为什么两个图层相交的时候,会有成组和悬浮两种类型的布局构造呢?咱们看下上述成组布局、悬浮布局两个设计稿中别离标出了相交的元素 A、B,它们在地位上的绝对关系是一样的,都是 A、B 两个图层对应的矩形框产生了穿插。然而咱们心愿现实态的 DSL 视图树却有所差别,如下图所示:

  • 成组布局中:A、B 逻辑上是一个整体,穿插是必然的,最终 DSL 中 A、B 被层叠布局蕴含,层叠布局中没有其余元素。
  • 悬浮布局中:A、B 逻辑上不是整体,只是碰巧穿插了,最终 DSL 中 A、B 别离在不同的层级中。

因而,对于图层相交时可能有两种类型的布局构造,别离是成组布局和悬浮布局。从上图能够看出应用成组布局还是悬浮布局是由图层内容决定的,那么就须要算法了解图层内容了,比方基于 AI 构建样本库,记住所有的角标款式(下面表格中 4 形容的),下次遇到角标相交时就生成成组布局。思考到 AI 模型也是对规定的形象,咱们先搭建一套自定义辨认规定。成组布局其地位信息是有法则可循的,例如:角标经常出现在右上角,标签经常出现在左上角,头像常常横向或者纵向穿插等,因而咱们针对图层之间的地位关系构建了穿插模型,如下图所示:

上图的穿插模型能够记住历史模板中成组布局图层之间的地位关系,下次遇到相交布局时判断是否在历史规定库中即可实现辨认,如果在就按成组布局解决否则依照悬浮布局解决。下图是通过历史模板构建的成组规定库。

下面介绍了本计划中波及的 5 种布局类型,目前来看这五种布局类型能够形容所有的模板布局,并且生成代码合乎 RD 的预期。上面展现两个设计稿 DSL 实例:


利器三:模型评估

在介绍横竖切割时,能够看到当存在多个切割点时,对所有切割点同时进行了切割,但实际上算法在切割时复杂度会更高,当有三个切割点时,实际上有 5 种切割形式,每种切割形式都会生成一个 DSL。既然有 5 种切割形式,那么到底应该抉择哪一种 DSL 呢?模型评估算法就是用来解决这个问题的。

目前模型评估算法有两个指标:布局节点数和逆布局指数。

  • DSL 中布局节点数越少,切割形式越好。
  • 逆布局指数用来评估 DSL 中的行列布局的正当水平,其中逆布局指数越大越不合理,反之,逆布局指数越小,切割形式越好。

以下图为例,看下视图不同切割形式下对应的模型评估形式:

如果模型评估算法只掂量布局节点数的话,那么会抉择第一种切割形式生成的 DSL 作为最终的后果。但实际上,第二种切割形式更加正当。在切割形式一中,广告、立刻预约处于一个列布局中,然而横向对齐形式(穿插轴)却不一样,“广告”是右对齐,“立刻预约”是左对齐,逆布局指数示意穿插轴对齐形式不统一的节点数量,因而通过逆布局指数,咱们能够躲避掉不合理的切割形式。

2.1.5 列表布局

上一节介绍了根本的布局构造,尽管说这些布局构造曾经能够形容所有的 UI 布局,然而与 RD 的编码习惯还是有一些差别。

对于下面的布局,RD 通常不会把雷同的 item 写五遍,而是会将 item 放在一个相似于 ListView 的列表组件中,使代码看起来简洁易懂。因而在 DSL 生成阶段,除了辨认根本的行 / 列 / 蕴含 / 成组 / 悬浮布局外,还须要进一步辨认行 / 列布局中的元素是否造成列表布局。在试验过程中,咱们发现列表布局分为两种:单状态列表组件 多状态列表组件。上图中每一个 item 的布局构造都是一样的,咱们称为单状态列表组件,再来看一下多状态列表组件(如下图所示),每个 item 有多种状态(选中态和非选中态),并且不同状态的布局构造不统一。

对行 / 列布局中单状态列表组件的辨认,只须要比拟 item 子视图树的构造,子视图树结构统一则判断为单状态列表组件。对多状态列表组件的辨认咱们采取了自动识别 + 人工干预的形式,自动识别的形式比拟粗犷,只有行列布局中子 item 的宽 / 高靠近,并且子 item 不是根本组件(根本组件容易造成误判),就断定为多状态列表组件。具体算法是计算子 item 宽高的标准差,小于阈值就断定为多状态列表组件,否则不是。公式如下:

那为什么还要人工干预呢?因为是否应用列表组件其实与产品逻辑相干,然而目前咱们无奈将产品文档中的逻辑辨认进去,只能尽可能辨认出所有的多状态列表组件,并容许用户对生成后果进行变更。比方上述送恋人的设计稿,产品可能约定每一个 item 都有选中态 / 非选中态两种状态,也可能是从业务角度思考须要着重突出送恋人这个 item,这时每个 item 就只有一种确定的状态,这两种不同的产品逻辑在编写代码时有不同的最优技术计划。

2.2 视图树转代码(DSL2Code)

DSL 视图树只是生成代码的两头产物,还须要对 DSL 进行代码还原,DSL2Code 次要包含两个步骤:属性推断、属性信息调整。

2.2.1 属性推断

属性推断包含两个局部:款式属性和构造属性。款式属性包含字体、背景色、圆角等能够间接通过数据源信息中获取失去的属性;构造属性包含大小、内外边距、主辅轴对齐等构造信息,这些信息无奈从数据源中间接获取,所以构造信息的推断是这部分工作的重点。

构造信息推断算法同样应用递归算法作为主框架,通过一次递归对所有元素进行两次遍从来实现构造信息的推断。如下图所示,在对 DSL 所有节点进行递归遍历时,把所有元素顺次退出队列中,递归实现后,再把所有节点顺次移出队列,这样一进一出便对所有元素实现了两次遍历,咱们把这两次遍历称为进队遍历和出队遍历。

进队遍历时,推断算法依据数据源中信息记录每个节点的大小和地位信息,并依据地位关系计算每个子节点在父节点中冀望的主辅轴对齐形式和内外边距。出队遍历时,父节点会依据子节点冀望的对齐形式确定父节点最终的主辅轴对齐形式,并依据子节点的拉伸用意修改父节点的大小。拉伸用意即节点的大小不固定,依据显示内容不同,在程度或垂直方向上可能会变大或变小,例如文本节点依据显示字数的多少长度会发生变化,字数过多时甚至还会换行。

2.2.2 属性信息调整

因为输出源是基于设计稿出现的动态效果图,设计稿中每个元素缺失了实在的业务含意,同样的展现成果在不同的业务场景中会有不同的属性要求,对于这部分内容,咱们无奈从输出源中进行精确推断。为此,咱们提供了可视化的属性信息调整性能来辅助代码生成,页面成果如下图所示,在这个页面能够对 DSL 中的所有节点属性进行查看和批改调整。

通过业务信息补充后,便可进行最初的主动代码转化,通过语法映射主动把 DSL 转化成 MTFlexbox 模板代码。

3 成绩展现

上面是设计稿间接生成代码未经批改展现后的手机屏幕截图,能够看到获得了不错的还原成果:

以上就是咱们近期对代码主动生成的摸索及实际,后续咱们将引入机器学习及神经网络算法,对过程进行进一步优化。如果您有其余的认识或倡议,也欢送在文末进行评论,或者跟咱们分割。

作者简介

田贝、少宽、腾飞等,美团平台终端业务研发团队研发工程师。

团队简介

美团平台终端业务研发团队的职责是保障平台业务高效、稳固迭代的同时,继续优化用户体验和研发效率。团队负责的业务次要包含美团首页等千万级 DAU 高频业务以及分享、账号、音 / 视频等根底业务,撑持和对接外卖、酒店等 30 多个业务方。团队通过动态化能力建设,放慢业务上线速度,帮忙产品(PM)疾速验证业务选型,做出业务决策;架构 / 服务标准化体系建设,晋升前后端以及平台与业务线的沟通、单干效率;业务监控和体验优化,无效保障外围业务服务成功率的同时,晋升用户应用美团 App 过程中的稳定性和流畅性。团队开发技术栈包含 Android、iOS、React Native、Flexbox 等。

招聘信息

美团平台终端业务研发团队是一个生机四射、对技术充斥激情的团队,现诚聘 Android、iOS、FE 工程师,欢送有趣味的同学投简历至 tech@meituan.com(备注:美团平台终端业务研发团队)。

浏览美团技术团队更多技术文章合集

前端 | 算法 | 后端 | 数据 | 平安 | 运维 | iOS | Android | 测试

| 在公众号菜单栏对话框回复【2020 年货】、【2019 年货】、【2018 年货】、【2017 年货】等关键词,可查看美团技术团队历年技术文章合集。

| 本文系美团技术团队出品,著作权归属美团。欢送出于分享和交换等非商业目标转载或应用本文内容,敬请注明“内容转载自美团技术团队”。本文未经许可,不得进行商业性转载或者应用。任何商用行为,请发送邮件至 tech@meituan.com 申请受权。

正文完
 0