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

简介: 作为阿里经济体前端委员会四大技术方向之一,前端智能化项目经历了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 的使用成本。我们正在努力通过智能化的手段来降低这些成本,让生成代码更加智能,更加简单。
相关文章
|
2月前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
Flex 布局 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。 2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。 一、Flex 布局是什么? Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
257 0
|
3月前
|
机器学习/深度学习 算法 调度
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
360 0
|
5月前
|
前端开发 搜索推荐 开发工具
通义灵码与颜色板生成器,为前端开发提供智能配色解决方案
在前端开发中,色彩搭配对用户体验和界面美观至关重要。通义灵码提供的颜色板生成器通过自动推荐配色方案、随机生成颜色组合及支持自定义调整,帮助开发者高效完成配色任务。该工具支持一键导出为 CSS 样式表,并提供简洁的中文指令交互方式,大大提升开发效率,助力开发者打造美观和谐的用户界面。
|
3月前
|
人工智能 前端开发 JavaScript
前端工程化演进之路:从手工作坊到AI驱动的智能化开发
前端工程化演进之路:从手工作坊到AI驱动的智能化开发
621 18
前端工程化演进之路:从手工作坊到AI驱动的智能化开发
|
7月前
|
机器学习/深度学习 数据采集 算法
智能限速算法:基于强化学习的动态请求间隔控制
本文分享了通过强化学习解决抖音爬虫限速问题的技术实践。针对固定速率请求易被封禁的问题,引入基于DQN的动态请求间隔控制算法,智能调整请求间隔以平衡效率与稳定性。文中详细描述了真实经历、问题分析、技术突破及代码实现,包括代理配置、状态设计与奖励机制,并反思成长,提出未来优化方向。此方法具通用性,适用于多种动态节奏控制场景。
260 6
智能限速算法:基于强化学习的动态请求间隔控制
|
3月前
|
算法 安全 定位技术
【创新未发表】【无人机路径巡检】三维地图路径规划无人机路径巡检GWO孙发、IGWO、GA、PSO、NRBO五种智能算法对比版灰狼算法遗传研究(Matlab代码实现)
【创新未发表】【无人机路径巡检】三维地图路径规划无人机路径巡检GWO孙发、IGWO、GA、PSO、NRBO五种智能算法对比版灰狼算法遗传研究(Matlab代码实现)
258 40
|
8月前
|
人工智能 自然语言处理 算法
阿里云 AI 搜索开放平台:从算法到业务——AI 搜索驱动企业智能化升级
本文介绍了阿里云 AI 搜索开放平台的技术的特点及其在各行业的应用。
861 3
|
7月前
|
传感器 人工智能 算法
企业内训|智能调控系统算法与优化——某汽车厂商
5月9日,东北某市,TsingtaoAI团队为某汽车厂商的智能驾驶业务和研发团队交付“智能调控系统算法与优化”课程。 本课程系统化解析智能调控系统的核心算法原理与前沿优化技术,深度融合经典控制、现代控制及模型预测控制(MPC)三大理论体系,聚焦自动驾驶与工业自动化场景的实践需求。课程从硬件层(传感器、异构计算芯片、执行器)到软件层(闭环反馈、实时优化)逐层拆解系统架构,结合车辆横纵向控制等实际案例,详解PID参数整定、LQR最优控制、MPC多目标优化等关键技术。
191 16
|
7月前
|
自然语言处理 前端开发 IDE
用通义灵码全新智能体+MCP实现从设计稿到前端代码,个人免费用
通义灵码全新升级,发布国内首个支持“自主决策+工具链闭环”的编程智能体,面向个人免费!新增功能包括智能体模式、混合推理模型Qwen3支持、全面集成MCP中文社区(涵盖2400+服务)及长期记忆能力。用户可通过IDE插件使用,兼容主流开发环境如JetBrains、VS Code和Visual Studio。教程展示如何将MasterGo设计稿转化为前端代码,简化开发流程。探索链接:[通义灵码官网](https://lingma.aliyun.com/)。

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    547
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    212
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    211
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    153
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    257
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    383
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    168
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    106
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    177
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    242