前端代码是怎样智能生成的-布局算法篇-阿里云开发者社区

开发者社区> 温柔的养猫人> 正文

前端代码是怎样智能生成的-布局算法篇

简介: 作为阿里经济体前端委员会四大技术方向之一,前端智能化项目经历了2019双十一的阶段性考验,交出了不错的答卷,天猫淘宝双十一会场新增模块79.34%的线上代码由前端智能化项目自动生成。在此期间研发小组经历了许多困难与思考,本次《前端代码是怎样智能生成的》系列分享,将与大家分享前端智能化项目中技术与思考的点点滴滴。
+关注继续查看

作为阿里经济体前端委员会四大技术方向之一,前端智能化项目经历了2019双十一的阶段性考验,交出了不错的答卷,天猫淘宝双十一会场新增模块79.34%的线上代码由前端智能化项目自动生成。在此期间研发小组经历了许多困难与思考,本次《前端代码是怎样智能生成的》系列分享,将与大家分享前端智能化项目中技术与思考的点点滴滴。

概述

在D2C中,设计稿(Sketch、PSD)、图片(JPG、PNG)经过算法处理之后,最终会导出以绝对布局为基础的元素信息。绝对定位的布局不具备扩展性,可读性也很差,对于开发者来说并不具有可维护性。因此,需要经由布局算法层来处理转化成“前端”眼中可用的代码。在布局算法处理之后,结合语义化、智能字段绑定、智能业务逻辑添加,最终为用户提供一份可读、可维护的代码,本文重点阐述布局算法层的相关处理过程。

所在分层

如图所示,经过链路中的物料识别和图层处理加工,会输出一份以绝对定位为基础,包含了元素位置信息和CSS属性的JSON数据。这份JSON数据接下来会进入布局算法层,对元素的布局结构以及CSS属性进行进一步的加工和处理,最终输出一份符合D2CUI图层协议规范的JSON数据。

image.png
(D2C 技术能力分层 )

如图所示,经过链路中的物料识别和图层处理加工,会输出一份以绝对定位为基础,包含了元素位置信息和CSS属性的JSON数据。这份JSON数据接下来会进入布局算法层,对元素的布局结构以及CSS属性进行进一步的加工和处理,最终输出一份符合D2CUI图层协议规范的JSON数据。布局算法作为D2C链路中的重要一环,需要为下游输出正确的布局结构、正确的样式属性、元素间的关系。目前包含以下:

  • 合理布局嵌套:

    • 绝对定位转相对定位
    • 合理的绝对定位
    • 冗余嵌套删除
    • 合理分组嵌套
    • 循环识别
  • 元素自适应:

    • 元素本身扩展性:文本、图片等节点位置自适应,大小可扩展
    • 元素间对齐关系
    • 元素最大宽高容错性

约束和前提

布局算法的目标是对任意视觉稿都能有良好的布局还原结果,但是在实际情况中,不够规范的视觉稿(图层分类混乱,图片大小不准确,元素位置不准确)都会影响布局的结果,因此正确的布局前提是有一份规范的视觉稿,这也是布局算法在现阶段,取得理想布局结果的一个前提。

此外,在真实使用的时候,虽然还没有编码,但是开发者早已洞悉视觉稿要怎么变成代码。但是由于规则的缺陷,或者视觉稿的不规范,生成的代码结果可能会与开发者心中所想有差别。因此我们需要提供能力让开发者可以干预生成的结果,而不是将整个过程包装在黑匣子中。这也是 imgcook 设计稿协议诞生的来由之一。通过这一套协议,开发者能够精确的控制代码生成的结果。换而言之,可以通过调整设计稿,结合设计稿的协议来达到对布局还原结果的控制,让生成的代码满足开发者的需要。

核心功能

布局算法的核心思路是分析布局中各个元素的位置、大小和类型,结合元素间的关系,将其从绝对定位的布局,转化为相对定位的布局。

image.png
(算法流程图)

如上图所示,布局算法的整个流程是顺序流式的,对于 JSON 数据处理的完整流程是:

  1. 节点预处理
  2. 矩阵识别
  3. 阈值处理
  4. 节点关系分析
  5. 行列结构生成
  6. 布局样式生成

输入

为了减少 Design 对还原的结果的干扰,如下图的设计稿,图层的组织结构和代码的 DOM 组织结构不同。在设计稿中,改变图层顺序,视觉结果可能都不会有变化,但是如果在代码中,调整了 DOM 元素位置,渲染结果可能会发生巨大的变化。因此,为了减少设计稿对还原的结果的干扰,我们选择将输入的设计稿的层级结构都去掉,让所有的图层变成一个一维结构,还原的时候不依赖设计稿提供的结构信息(大部分情况下这些信息都是错误的)。

image.png
(设计稿示例图)

这带来的问题是,设计稿中的结构信息丢失。最终的 DOM 结构完全由布局算法生成,失去了人为干预的能力。开发者想要调整 DOM 结构,只能在布局算法生成之后。这会大大降低开发体验,提高使用成本。因此,我们设计了成组协议,通过在设计稿图层名称上添加 #group#,告诉布局算法,设计稿中这个结构是正确的,不需要重新计算。通过成组协议,能够满足开发者对于 DOM 结构干预的诉求。

节点预处理

布局的算法输入来源有 Sketch 插件,PS 插件以及图片,同时,随着插件的迭代升级,不同版本的插件导出的格式和内容也会有所不同。所以需要在进入布局算法之前,将这些差异所以抹平,确保布局算法处理的过程中不要为这些兼容性问题进行编码。

矩阵信息

从这一步开始,布局算法正式开始布局的计算。上面已经提到,输入的 JSON 里是不包含元素的结构信息。因此我们需要通过元素的位置和大小来分析出结构信息。

分析的第一步就是构造一个与输入大小一致的矩阵,例如输入是 702x370 的一个模块,那么会构造一个 702x370 大小的矩阵。遍历 JSON 中的所有节点,根据元素的位置和大小在矩阵中标记元素所在的位置。

这一步的主要工作就是填充整个像素矩阵,得到元素的交错记录。

image.png
(图层信息转矩阵信息示意图)

如图所示,JSON 结构信息会转化成一个像素矩阵,像素点上会记录包含的元素信息。

阈值处理

设计稿设计的时候可能有误差,图层的位置可能可能会有偏移,肉眼去看的时候不会很明显。但是在还原步骤中,分析像素矩阵的时候,是会对每一个像素都进行分析,所以像素级别的误差都会被记录进来,对结果可能会产生巨大的干扰。所以需要有一个步骤去规范图层,自动去修复这些误差,降低对还原结果的干扰。

image.png
( 阈值处理 )

如上图所示,元素间存在的误差需要我们去分析处理,将这些误差消除掉,为后续的处理提供一个可靠的结果。

节点关系分析

得到准确的矩阵信息之后,就可以来分析元素间的关系。根据元素间的位置信息,可以定义一下三种关系:包含、部分重叠、完全重叠。

image.png
(节点关系)

如图所示。A 包含 B 说明 B 节点可能是 A 节点的元素;A 和 B 局部重叠,说明A和B中至少有一个元素需要进行绝对定位。A 和 B 完全重叠的情况较为少见,但是也更为复杂,说明可能其中有一个元素是多余的,也有可能是一个节点包含另外一个节点,也有可能是有节点需要进行绝对定位。经过这个步骤,我们能够获得所有节点之间的关系,可以输出给下一步进行节点结构的构造。

行列结构生成

布局算法是通过“行列结构”来描述布局结构。“行列结构”记录了布局的行列信息,一行的信息包含有:行的起始位置,行的结束位置,行包含的元素,行里面包含的列。一列的信息包含有:列的起始位置,列的结束位置,列包含的元素,列里面包含的行。

image.png
(行列结构示意图)

如图所示的一个模块结构,首先会被分成两列记为 Col1 和 Col2,可以看到Col2 里面还包含了三行,可以记为 Row1,Row2 和 Row3。Row3 里面又包含了三列,可以记为 Col1、Col2、Col3。如图六右侧结构示意,最终生成从行列结构是一个树状的结构。

通过元素的行列结构信息,我们可以计算元素的布局信息。在图六的这个例子里,根节点包含了两个子节点 Col1 和 Col2,这两个节点在纵向可以通过 margin-Top 来设置与根节点容器的边距,在横向可以通过 spaceBetween 来设置两个节点的位置。再进一步计算 Col2 中的 3 个 Row 的布局,通过递归的方式,计算所有节点的布局信息,建立完整的布局关系。

这个步骤是布局算法中最为关键的一步,但是行列结构生成的结果并不是唯一确定的。像图六这样的模块,还可以生成下图这样的行列结构。

image.png
(另外一种行列结构)

不同的行列结构描述代表了不同的 DOM 结构,从 UI 信息上,有时候并不足够判断哪种行列结构是最优的。所以引入了成组的协议来增加开发者的干预,确保能够生成开发者期望的结构。

需要注意的是,这里生成的 DOM 结构可能不是一棵树,而可能是多棵树,比如有一些 DOM 节点是绝对定位的,这部分节点会独立组成一棵树,而没有在主干上。

布局样式生成

经过上一步行列结构的生成,得到了多棵 DOM 树。接下来进进入了布局样式生成的步骤。这一步会遍历上一步得到的所有行列结构,将分散的多棵树组织成一棵完整的 DOM 树。得到完整的布局结构之后,节点的样式需要进一步优化。

  • 宽高优化:上游给到的输入,所有的节点都会有宽高信息,但是经过布局算法处理之后,部分节点可能不需要这个宽高属性,而是由子节点将容器撑开即可。
  • 样式精简:删除插件导出的多余属性
  • 属性处理:插件中的 transform 是针对单个节点,但是布局之后的 transform对子节点也会生效,所以要对 transform 属性进行处理
  • 扩展性优化:有一些元素是可扩展的,例如【图三】的牛皮癣节点,需要进行样式的优化,如果设置了容器宽度需要转化为 padding 形式的布局
  • 层级优化:对生成的 DOM 树进行层级优化,删除一些多余的层级

经过上述处理之后,就得到了完整的 DOM 树,布局算法的基本任务也已经完成。生成 DOM 树最后,可以进行进一步分析,例如可以对 DOM 树的节点相似度进行检测,标记可能是循环的节点。检测出循环之后,在生成代码的时候节点就可以通过循环的方式渲染。

测试和度量

由于布局算法目前还偏向专家规则系统,深度学习等智能化方案应用较少,所以规则分支较多,改动容易引起关联问题,所以布局算法层对功能的稳定性和效果的度量有非常高的要求。

功能稳定保障

单元测试

布局算法许多函数的输入非常复杂,像是矩阵信息,可能就是一个 702*458 这样的一个矩阵,构造这样的输入很困难。于是我们另辟蹊径,不直接构造函数的输入,而是在设计稿中构造不同的模块,以一个完整模块的运行作为测试用例。

不仅输入的构造较为困难,输出的对比也不太容易。假如要分析矩阵信息这一步骤构造的矩阵是否正确,我们的结果需要录入 702*458 这样的结果。虽然确实可以通过这种方式测试,但是我们设计了另外一种方法,将多个函数联在一起,最终输出的是一个对象,这样测试结果的可读性也大大增强,同时也能保证的正确性和测试的有效性。

目前单元测试的代码覆盖率达到了 78%,核心功能达到了 100%。

功能测试

除了单元测试外,在布局算法的场景下还可以通过功能测试来保障算法的正确性。精选了线上的 156 个模块作为测试集,包含了无线,pc 等各种场景下的模块,运行布局算法,分析算法运行的结果。在每一次上线前,都会运行一轮功能测试,以保证布局算法功能的正确性。

效果度量

测试上保证的是布局算法对不对,有没有报错。但是对于结果的“好不好”,需要通过另外一套体系来度量。这套度量体系包含了三个方面:UI 还原度量,代码可维护性度量,用户真实可用率度量。

UI 还原度量

UI 还原度量是度量经过布局算法后视觉效果上是否 100% 还原,具体是通过对比模块的视觉图和 demo 截图,分析布局算法是否准确地还原了模块。

image.png
(UI 还原度量)

布局还原效果度量方案复用了插件的还原度量方案,度量插件的还原度时,使用的是插件导出的 JSON 数据,而度量布局算法的时候使用的是还原的结果。还原精选了线上 160 个模块,覆盖了多种形式的布局,经过还原对比,确保布局算法的准确性。不过 ui 的度量只能保证说渲染出来的 UI 和视觉稿一致,但是不能确保结构的正确,假如没有经过布局算法的加工,直接是插件导出的数据,可能对比设计稿还原度会更高,因此需要其他的方案来进一步度量还原的结果。

代码可维护性度量

可维护性的度量,主要是考虑度量代码本身的质量。代码的质量可以通过结构的合理性来衡量:嵌套不能过深,节点数不能太多,不能有多余的嵌套。从生成的节点结构来分析布局算法的可维护性,具体度量的方法:

  • 嵌套

    • 最大嵌套深度不超过 6 层
    • 冗余嵌套(1 套 1)
  • 子节点数

    • 不能超过 6 个

虽然方法较为简单,但是从结果看能够很好的描述生成的结构是否冗余。但是,这种程度的度量也还不足以描述生成的代码足够好,因此我们还引入了用户真实可用率,来进行共同度量。

用户真实可用率度量

如何判断用户的认可度就比较难,如果直接进行用户调研,会有一定的主观因素,也难以量化。我们想到的方法是,计算代码的改动比例,如果生成的代码得到了用户的认可,满足了用户的需求,那么他就不应该去改动代码;反之,如果生成的代码不好,存在问题,用户拿去使用的时候一定会去修改。用户保留下来的代码的比例可以一定程度上用来衡量用户的认可度,从而反应了还原的效果。

度量的计算方案:

  • 代码可用率:生成的代码最后留存行数 / 发布阶段的总代码行数

双十一模块的度量结果

此次双十一,双 11 新增模块总数 38,D2C 链路产出 30 个,占比:78.9%,智能生成代码平均可用率:79.34%,视图还原准确度:92.47%。未来重要努力目标之一,就是不断的提高视图还原准确率,提高代码可用率。

未来展望

目前,经过规则协议的推广,我们得到了大量用户标记了成组和合并协议的视觉稿,通过对比去掉协议之后的结构生成结果,可以分析出算法生成的结构与用户期望的结构的差别。借助这些高质量的样本,我们正在通过机器学习的算法,进行智能的成组和合并,进一步的降低用户使用的门槛和成本,解放生产力。另外,补充目前整在努力的一些方向:

  1. 布局算法当前只支持 flex 布局,但是中后台场景或者其他场景可能需要不同的布局方案,因此布局算法后续会提供布局的定制,可以从 flex 布局切换到其他布局。
  2. 提高布局的准确度,目前有些场景下,布局结果和业务实际场景有关,布局还原的效果不理想。接下来会提供辅助的工具,在插件上引导设计师规范视觉稿,在 web 编辑器上给开发者更好的编辑体验。
  3. 降低开发者的使用成本,目前对于设计师,前端,在使用过程中还有调整设计稿的要求,这也提高了 D2C 的使用成本。我们正在努力通过智能化的手段来降低这些成本,让生成代码更加智能,更加简单。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
写一个通用的代码生成器
       代码生成器对于JAVA码农来说并不陌生。在一些业务性比较强,但编码比较规范的项目中,往往会有大量的重复或者类似的代码要写。比如对表的增删改查,比如生成用于远程调用的客户端方法存根等等。面对这种情况,程序员通常的做法就是拿一个现成模块的代码copy过来再改改。
2916 0
排序算法大数据量测试代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Diagnostics; using System.IO; namespace Sort { class Program
829 0
手把手教你生成对抗网络 GAN,50 行代码玩转 GAN 模型!
本文为大家介绍了生成对抗网络(Generate Adversarial Network,GAN),以最直白的语言来讲解它,最后实现一个简单的 GAN 程序来帮助大家加深理解。
1625 0
DL之RNN:人工智能为你写代码——基于TF利用RNN算法实现生成编程语言代码(C++语言)、训练&测试过程全记录(二)
DL之RNN:人工智能为你写代码——基于TF利用RNN算法实现生成编程语言代码(C++语言)、训练&测试过程全记录
29 0
从P4到P9, 在马云家写代码到双11前端PM
阿里妹导读:今年的双11已经是阿里资深前端技术专家舒文来阿里的第11年,从应届生到双11前端PM,他一路升级打怪,实现了岗位上从P4到P9的晋升。这第11届双11顺利结束之际,他把在阿里这些年的成长经历做一个总结和分享,希望你能在他的故事中得到些许启发。
18514 0
双 11 模块 79.34% 的代码是怎样智能生成的?
作为今年阿里经济体前端委员会的四大技术方向之一,前端智能化方向一被提及,就不免有人好奇:前端结合 AI 能做些什么,怎么做,未来会不会对前端产生很大的冲击等等。本篇文章将围绕这些问题,以「设计稿自动生成代码」场景为例,从背景分析、竞品分析、问题拆解、技术方案等几个角度切入,细述相关思考及过程实践。
9315 0
Web前端,让你代码整洁的原则
写Web页面就像我们建设房子一样,地基牢固,房子才不会倒。同样的,我们制作Web页面也一样,一个良好的HTML结构是制作一个美丽的网站的开始,同样的,良好的CSS只存在同样良好的HTML中,所以一个干净的,语义的HTML的优点很多,那么平时制作中,我们做到了这一点吗?我们一起来看一张图片:   上图展示了两段代码,我想大家都只会喜欢第一种,我们先不说其语义,至少他的结构让我们看上去清爽,而第二种呢?一看就是糟糕的代码的代码,让人讨厌的代码。
917 0
深度学习中正则化技术概述(附Python代码)
欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习、深度学习的知识! 磐石 介绍 数据科学研究者们最常遇见的问题之一就是怎样避免过拟合。
1729 0
1172
文章
2
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载