用户登录界面设计代码html_DSL 与界面设计杂谈

首发语雀:

DSL 与界面设计杂谈​www.yuque.com

设计工程化实践

C2D探索

C2D (Code To Design)比较知名的实践有 react-sketchapphtml-sketchapp

通过在前端写 react-native 式的代码,然后在 sketch 端就可以渲染输出成设计稿。理论上这是一种非常美好的设想:唯一的 source of truth 就是代码,通过代码生成设计稿,那么类似组件库这样的文件就可以变得工程可控。但是在生产端落地的过程中,遇到一个很大的问题,前端使用的代码和 react-sketchapp 编写的组件代码是两套代码。一旦经历版本升级,就很有可能导致版本不一致。额外维护一套代码的成本已经高过收益,因此这种方式最后被我们放弃了。

html-sketchapp 的思路不一样,后者可以直接识别 html 节点,并将其转换为设计稿。

基于这样的能力,我实现了表格自动生成和二次编辑的功能。(演示如下)

d0da2ea428ddddbcf5ae0ce7a5a18dbb.png

由于 html-sketchapp 这个包都是由 JS 写成,在使用过程中提示非常不完善。再加上要拓展这个库必须要懂它是如何实现的,所以我用 ts 将这个库进行了重构升级。

这个库的实现逻辑其实非常简单:将需要转换的 html 节点找到之后,计算其位置、宽度、文本、样式等数据,将其转换为符合 Sketch 的数据结构。最后导入到 sketch 中。

比如下图所示的一个矩形框,我们可以用 getComputedStyle 方法得到这个矩形的所有样式信息。(在浏览器的 Computed 里即可查看到)从下图我们可以看到,这个 div 对象的背景颜色、边框颜色、圆角宽度等等信息都可以获取到。

b6b8e02a79c7f217eb09cb2d3457dcea.png

然后接下来就是将提取这些信息,转换为相应的 Sketch 对象。由于 Sketch 的文件数据结构已经开源出来,所以这一步转换变成了可能。

比如上述这个矩形转换为 Sketch 对象,生成出来了 170 多 行代码。

{
  "booleanOperation": -1,
  "edited": false,
  "fixedRadius": 0,
  "hasClickThrough": false,
  "hasConvertedToNewRoundCorners": true,
  "isClosed": true,
  "isFixedToViewport": false,
  "needsConvertionToNewRoundCorners": false,
  "numberOfPoints": 0,
  // ... 过多省略
  "points": [],
  "sharedStyleID": "",
  "_class": "rectangle",
  "do_objectID": "19727987-E66D-4752-BE76-DDCA5AFBBC35",
  "isFlippedHorizontal": false,
  "isFlippedVertical": false,
  "isLocked": false,
  "isVisible": true,
  "layerListExpandedType": 0,
  "name": "rect",
  "nameIsFixed": false,
  "resizingConstraint": 63,
  "resizingType": 0,
  "rotation": 0,
  "shouldBreakMaskChain": false,
  "layers": [],
  "clippingMaskMode": 0,
  "hasClippingMask": false,
  "frame": {
    "_class": "rect",
    "constrainProportions": false,
    "height": 36,
    "width": 2000,
    "x": 0,
    "y": 0
  },
  "pointRadiusBehaviour": 1
}

其中最关键的一步,也是非常 dirty 的一步,就是分析各种样式,然后转换成符合 sketch 文件格式的代码。

但是由于 sketch 只有绝对坐标,没有布局引擎的概念,所以要知道一个对象的位置,必须去计算出它在浏览器中的位置。

比如当文本在 html 中左中右对齐时,其 x 坐标的计算可能就要如下所示:

// 如果是左对齐
if (textAlign === 'left') {
  // 确认下 padding 的距离
  const pl = parseFloat(paddingLeft);
  x = x + pl;
}
// 如果是居中对齐
if (textAlign === 'center') {
  x = x + nodeBCR.width / 2 - textWidth / 2;
}
// 如果是右对齐
if (textAlign === 'right') {
  // 确认下 padding 的距离
  const pl = parseFloat(paddingRight);
  x = nodeBCR.right - textWidth;
  x = x - pl;
}

所以理论上来说,有了这样的一个HTML解析器之后,我们就能够将这份 HTML 文件一模一样地解析成任意的 sketch 对象(如全局样式、Symbol等等),达到代码转设计的目的。由于这个解析器只对最终的 HTML 渲染样式负责,所以这份 HTML 可以由任意的前端框架来实现。无论是 Vue、React 都可以达到一样的效果。

SlateJS 开发经历

实现完这个 HTML 解析器,不由得让我想起不久前我使用 Slate 编辑器 (就是语雀编辑器的前身)的经历。Slate 的官网其中一个 demo 让我印象非常深刻。

这个 demo 实现的功能其实很简单——复制 HTML 文本时保留格式。其 demo 的实现方式是:解析复制过来的 html 节点类型,然后转换为 JSON 对象插入到JSON文档对象中,再将 JSON 文档对象按照编辑器已有的渲染规则将其展示出来。

共通点

在某种意义上这个 demo 的实现思想和 html-sketchapp 是一致的:将已有的某种结构的对象解析为通用的数据结构体,然后再通过相应的规则实现目标对象的转换。

如果把这两个问题放在一起看,做一层抽象,其实它的本质是一回事,即:在通用/抽象层面我们该如何去描述相应的问题域?

DSL与设计工程化

DSL介绍

所以到这里,DSL 的出现变得自然而然。DSL(Domain Specific Language)的中文文翻译为【领域特定语言】(下简称 DSL)。有对比才能更好去理解这个概念,所以可以简单说一下 GPL(General Purpose Language),即【通用编程语言】,也就是我们非常熟悉的 JavaScript、Python 以及 Java 语言等等。而我们常见的 DSL 包括 HTML、Regex(正则表达式)、Markdown 等,甚至React 也可以作为一种 JS 的内部 DSL 来看待。

DSL 往往有下述几个特征:

  • 没有计算和执行的概念;
  • 其本身并不需要直接表示计算;
  • 使用时只需要声明规则、事实以及某些元素之间的层级和关系

世界级软件工程师 Martin Fowler 对 DSL 的看法我认为非常有穿透力:DSL 通过在表达能力上做的妥协换取在某一领域内的高效

例如 markdown 仅仅是规定了几种非常简单的语法规则,就极大地提升了文档的书写能力,同时也给样式的自定义留了巨大的空间。(关于这部分的讨论,有兴趣可以查看我另外一篇文章:此处为语雀文档,点击链接查看:https://www.yuque.com/arvinxx/note/mdk2bd)

DSL 的本质在某种意义上和我们去解决通用问题的思路一样——通过限定问题域边界,牺牲域外的一部分(乃至全部)灵活性,带来域内效率的提升

更多关于 DSL 的介绍,推荐几篇不错的文章:

  • 前端 DSL 实践指南(上)—— 内部 DSL
  • 如何写一个类似 LESS 的编译工具?

DSL 在设计工具的应用

DSL可以帮助我们更加快速的去描述问题域,好的DSL会具有极好的描述力和扩展性(例如React是一个很好的前端视图层的DSL、markdown是一个很好的书写域的DSL)。一个不好的DSL在描述这个领域时就会显得捉襟见肘。

如果我们从 DSL 的角度出发来看待设计工具,Sketch 从几年前开始在交互、视觉设计领域逐渐流行的原因可见一斑。

在界面设计(UI)的这个问题域中,我们基本上可以抽象出常用的绘图对象是矩形、圆角矩形、椭圆(正圆)、直线、多边形(星形)、自由路径和自由形状这几种。而图形的样式基本只需要描边、填色、内外阴影、模糊这几种。

所以在全世界交互设计发展的初期阶段, Sketch 准确构建了界面设计问题域中的关键要素,通过牺牲了绘图的灵活性(比如无法绘制特别复杂的花纹等),带来了UI领域的高效。就我个人而言,Sketch 其实就是一个阉割版的 AI(Adobe Illustrator),Sketch 能实现的效果 AI 基本上都能实现。但是 Sketch 通过限定问题域,有效降低了工具上手的复杂度,在界面设计领域成功上位。

但是发展至今,已经有越来越多的声音在说 Sketch 要不行了,未来是属于 Figma 的等等的声音。

原因是目前的界面设计的发展已经进入了深水区,我们已经不再仅仅满足绘图层面的基础能力,我们希望能够获得更加全面,更加完善的交互设计效能的提升,比如团队协作、复杂组件智能生成、自动布局、设计转换为代码等等更加工程化的需求被提上台面。从 DSL 的角度来看,Sketch并没有在上述的一些环节中有所发力,所以大概是成也萧何败萧何吧~

比如在布局这一层,Sketch 就缺少了对布局的抽象描述能力。例如下图这种场景的业务场景,如果我要多增加两个元素,我们很难按照已有布局的方式快速添加。如果 Sketch 的布局中某个对象尺寸发生变化,导致间距不一致时,我们往往需要手动去处理间距问题。在用户侧来看,这是 Sketch 的功能缺失。但是本质上,其实是 Sketch 在元素布局这部分缺少 DSL 层的梳理,使得sketch 缺少了描述常见布局的能力。

c87d2539a32a87373b270e07b4bc4854.png

可以与之明显对比的就是figma。figma中有一个功能叫 auto layout,可以实现类似浏览器中的Flex布局模型的效果,可以快速做到对齐、新元素自动布局等等特性。

222933f65c2053938efbcdb9f309fb6a.png

这同样导致的一个问题是目前现在基于sketch(还可以包含上ps xd)的D2C很难推进。因为Sketch缺少布局方式的描述信息,使得sketch生成的设计稿数丢失了设计师在布局层的「设计意图」(sketch 存储的数据基本只有绝对定位,缺少有效的相对布局信息)。

而通过上述演示的这个对比,我们可以发现如果利用 figma 产出的数据信息进行d2c,可能生成的代码可以更好的还原「设计意图」。

所以我可以大胆地做一个预言:一旦有良好的描述设计领域的DSL时,设计稿的描述能力将会有极大的提升,我们甚至可能围绕这样的设计稿延展出全新的设计开发流程。

例如未来我们有了一个全新的设计工具,这个设计工具基于一套有效的 DSL 进行开发和构建。利用这个设计工具制作的设计稿就能够完整地包含设计师的「设计意图」,当需要转换时,我们只需要按照相应的规范(例如 sketch 文件格式、前端代码语法规范)转译成相应平台的代码/文件,就可以在相应平台下进行使用。这将大大降低设计与开发之间的摩擦,达到极致提效的目标。设想一下:当你完成了设计稿,相应的前端代码就已经工工整整地生成完毕,前端工程师只需要完成功能逻辑的开发,不需要做走查,大家都能更早下班,这样的画面,想想不就觉得非常激动人心吗?

a65d41b8942f05633e2def1cec775699.png

DSL、D2C与人工智能

阿里经济体的 imgcook 前端团队写过不少D2C 相关的文章,例如 如何使用深度学习识别 UI 界面组件? 、前端代码是怎样智能生成的-布局算法篇 等。

在人工智能识别组件、生成代码的过程中, DSL作为其中的桥梁是非常核心的一环。我个人认为只要拥有一个良好的 DSL 能够完整高效地记录下设计稿中的设计意图,这样就能为 D2C 带来极大的可能性。

再举个不成熟的小例子:

如果我们对交互的业务侧做一些分类和整理,我们不妨用 @徐飞 老师 交互的本源 —— 对渐进式交互优化路径的初步探索 的观点来分类,

基于以上原则划分的交互形态,基本上都是可以同类互换的,将一种形态切换为另外一种,并不会影响业务实质。比如说,业务上想要表达布尔类型,可以在 Switch、Checkbox、RadioGroup、Select 中任意选取。

像这样的业务属性,如果能够在 DSL 中有所描述,就能够给人工智能生成前端代码带来新的可能性——即业务层逻辑组件的智能生成。

凡是可被定义,就有可能AI化。

DSL与设计

在往大一层去看,DSL 对设计有什么帮助?

我在知乎上看过一个问题的回答:

实现不了的需求太多了,我就说一个看上去特别简单的吧:
能不能给我设计一个DSL+runtime,让我可以轻松的描述出一个模型,从而得到一张表单,并且支持扩展?
如果这个DSL能做到易学易用(你别给我搞一个几百页的文档+培训才能用的东西),中后台管理页面的开发效率,可以轻松提升5到10倍。
大家可能不知道,你们用的企业内部系统里面,那些看起来无甚技术含量的增删改查页面,至今开发效率还低到让人难以忍受——一个月薪上万前端,每天只能调通一到两个表格+详情模块(哪怕他用了市面上的apaas),遇到字段较多,联动较复杂的模块,甚至两天才能调通一个。
这简直是在浪费生命。
ps:说一下我对这个问题的理解。
大家在评论里面推荐了一些库和低代码平台,这确实是前端热门领域之一,各家也都有做了几年的产品,开始陆陆续续借着aPaaS的风往外show。
但这个问题的核心,并不是低代码,也不是配置化,而是:
第一,我们到底应该如何为表单建模,然后设计一套语言去方便的描述它。
第二,这套工具是如何与平台集成在一起的,它吃什么,吐什么,如何扩展。
第二点先不说,关于第一点,我们能看到很多反例。有些产品做的很漂亮,拖拽编辑器,内置物料,内置数据流,看起来已经很完善了。但是你一用,总感觉它很孱弱,要么你挠掉头发也配不出你要的功能,要么是不是的就让你写js代码。
原因在于,这些产品没有从源头上解决问题——先把表单的数学模型搞清楚,再设计一套用户友好的DSL(不是配置文件,也不是schema)去描述模型,最后才是UI搭建部分。
如果你上来就从UI搭建开始设计,对于前两个问题不去深究,你设计出来的,就是“唯像”的产品,经不起折腾。
作者:欲三更
链接: https://www. zhihu.com/question/4032 44729/answer/1301175728
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

DSL 是描述问题域的语言,最核心的其实是对问题域的抽象和建模。所以在这里提一个自己造的新词:DSM(Domain Specific Model) ,中文我自个儿叫【问题域模型】。

如引用的内容所述,其实很多设计上的问题,本质上来看,就是 DSM 的抽象和设计问题。

就我自己个人对交互设计的理解,交互的实质就是数据状态的变化,用公式表示就是:

newState = Interaction(prevState)

再说个极端一点的观点辅助理解:交互的实质就是数据的增删改查

因为交互无非是基于下述了三个问题进行展开:

1、针对什么数据;

2、做什么操作(增删改查)

3、怎么操作(即操作状态和操作形式,例如独占态、临时态、精灵态)

而这三个问题本质上都是围绕 DSM 进行展开的。

JCD 方法论中有提到实体分析,其实某种程度上就是对 DSM 进行分析。只不过每个实体相对较小,而 DSM 则是包含了所有实体和实体之间关系的模型。

所以说,一个产品的体验设计得好,非常易用,有很大概率是 DSM 设计好了。而某个产品体验不好, 很多流程存在断点,大概率是 DSM 的设计存在缺陷,没有补齐。

一个抽象好的 DSM,无论是设计还是开发,都会带来很大的收益。

说的这么玄乎,那么 DSM 到底怎么去建模或者去抽象呢?说实话目前我也没有体系化的方式,大部分情况下也还是自底向上的方式瞎摸黑在做。如果有提炼某些经验的话,大致有两点:

  1. 对象模型层用 JSON 结构表达;
  2. 视图层用 JSX(React) 表达。

但是这一层有点太偏向开发,就不做进一步展开了。

总结

以前我都不太 care 交互设计的五层模型,尤其是战略层和信息架构层,觉得这个太泛太虚。但是如果从 DSL 和 DSM 的角度来看,信息架构层就变得非常重要和充实。我相信在 DSL 和 DSM 进行深入挖掘,一定能够发现一片新的天地。

以上,欢迎指教~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值