在历经两年多的迭代后,Odeon大数据平台在底层能力建设上已经至关丰满。最近大半年来在数据可视化方面也投入了很大的精力,目前自助 BI 产品也已经成功上线并稳定运行了一段时间,今天小剧就来分享下咱们在数据可视化中的一些经验。git
今天的分享主要围绕 可视化布局模块 的一些工做,布局模块是承载可视化图表的一块画布,是用户用来组织业务逻辑的重要手段之一。先来体验下 在线demo 或者看下面的效果图:github
图一:可视化布局模块效果图dom
其实不论是在数据可视化,仍是在一些自助发布的运营平台,自助布局一直是一个难以跳过的问题。在项目开始之初这个问题也一样在困扰着咱们,是咱们开发几套预置模版让用户挑选,仍是开发一套让用户可拖拽配置的布局模块?布局
前者实现上很是简单,也很容易设计的很是精美,可是缺乏了不少灵活性,很容易千篇一概。后者用户在使用上自由度很是高,能够拖拽出更符合本身预期的界面,可是开发成本相对较高,而且想要达到稳定、易用、高辅助性却比较难。性能
综合考虑上面的这些问题,咱们对制定的几套方案均不满意,最终仍是决定本身动手实现一个能够辅助用户进行拖拽布局的组件。大数据
通过设计,咱们对交互模型作了梳理,设计了卡片、图表两层结构。在此基础上对数据模型作了总体设计,结合上面效果图和 在线 demo 能够更加容易理解下面的划分。设计
首先是局部范围内单例的 Map 类,用来描述整个 dashboard 布局,以及其余数据存储。3d
其次是 Widget 类,用来定义卡片信息,包含卡片的尺寸、位置信息,以及更详细的卡片标题、卡片类型、脚注、图表ID 等信息。code
最后是 Chart 类,用来定义图表信息。为了布局与图表模型分离,这里的图表信息放置较少,仅仅存储了必要的 id 等字段,图表自己实现由外部 slot 插槽来完成。cdn
图二:数据模型
数据模型构建好了,接下来就是着手设计拖拽交互了。
出于响应式考虑,同时为了减小用户操做的随意性,在布局设计上咱们放弃了像素单位,而是针对节点尺寸设计了虚拟的 12 栅格切分,在初始化、缩放、移动时都严格参照此栅格布局。
为了保障用户拖拽体验的顺畅,使布局保持整齐,咱们在遵循卡片自动调整逻辑的基础上,设计了卡片的重绘流程,这一点在后面会有详细的介绍。
为了提供更好的拖拽体验,咱们额外设计了虚拟卡片用来辅助用户进行布局,用户随时能够预览松开鼠标后卡片处在的位置及大小,效果以下图阴影处所示。
图三:拖拽预览效果图
有上面的数据模型设计,其实一大半的困难已经被解决了。难点主要体如今辅助布局过程当中易用性上的一些处理,总结下来有如下几点。
其实单纯的碰撞检测是很容易解决的,毕竟全部卡片只是二维矩形而已,这一点并非难事,困难的是碰撞后被接触的卡片须要腾出位置进行让位,咱们须要找到全部被碰撞到的卡片,以及受此卡片影响的全部后续卡片,这是一个较为困难的点。
图四:碰撞检测布局重绘过程
在设计布局的过程当中,用户可能会把卡片拖得七零八落,并且在上面提到的碰撞检测的处理过程当中,也会致使相邻卡片受影响。初期的交互在体验后发现,拖拽过程当中用户须要花很长时间来从新整理布局,所以为了保证布局排列紧密,必需要有一个方法,可以将全部处于悬空状态的卡片依序吸顶处理。
图五:自动吸顶布局重绘过程
上面提到的这两个困难点,在移动、缩放这两个拖拽交互中都存在,而且逻辑上是一致的,所以在拖拽布局过程当中咱们抽象出了一套重绘逻辑,按顺序整理以下:
由于拖拽须要实时预览效果,上面这四步重绘逻辑会被频繁触发。为了不在布局过程当中反复污染真实的位置数据,咱们为卡片位置咱们引入了 previewOffset
字段,用来存放预览效果时的垂直偏移量。
可能会有同窗会产生一个疑问:这里是业务上的重绘逻辑,如此高密度的修改数据会不会在性能上表现比较差 ?
其实这个问题的解决得益于 Widget 类 的数据模型设计,在从碰撞检测到自动吸顶等一系列处理过程当中,被频繁计算、修改的仅仅为相对单位的 position
对象,而界面布局使用的是绝对单位的 screenPosition
对象。数据与表现是分离的,仅当一个重绘流程结束以后才去触发 screenPosition
的更新,如此设计使得界面更新节奏更可控,界面更稳定,避免了视觉上卡片位置的闪烁的问题。
按照此重绘逻辑,既避免了 dom 层冗余的重绘开销,提升了总体性能,又在界面布局的易用性上获得大大提高,操做体验上也更加稳定、流畅。
本文主要从可视化布局模块的交互逻辑的设计上展开,并未涉及到具体代码实现,做为 Odeon 大数据平台在可视化布局模块的一些思路,相信经过本文您已经有了初步的了解。
若是您对文中提到的碰撞检测、让位处理、吸顶效果以及辅助布局中等具体实现细节感兴趣,欢迎私下进行探讨,可能的话我会另开一篇文章详细展开来聊。