如何绘制一个类甘特图 (附源码)

数据体验技术团队(ProtoTeam) @ 蚂蚁金服(杭州)网络技术有限公司

作者简介 Kid 蚂蚁金服·数据体验技术团队

本文介绍如何从头绘制一个业务图表以及对于通用性上的一些思考。代码在最后也会给出。

效果演示

先看下组件的最后效果

xiaoguo.gif | left | 672x424

要画图,当然是先找找看有没有能够直接拿来用的。我需要绘制的是一个类甘特图。主要是为了做时间基线上的任务耗时管理,并且能够与过往耗时进行对比。与传统的甘特图定义有些区别。长相上与甘特图类似。

找了AntV,echarts,和D3。AntV和echarts都没有直接的甘特图。D3上有一些甘特图,但是和我想要的功能区别还是挺大的。基于他们修改的代价应该比自己画的代价高。那么挑哪种技术绘图呢,canvas,svg和div。我的业务场景绘制的点不算多,而且canvas对于事件挺难处理的。svg毕竟有DOM元素,一些hover效果我可以直接借用antd来做。最后选择了svg。(其实之前没画过图,用啥都得学~)

功能列表

  • 图表绘制
  • 上下滚动
  • 漫游器控制左右滚动以及缩放比例
  • 节点hover显示细节

整体设计

组件结构
未命名文件.png | left | 414x433

组件的设计就如上图所示了。图表与Y轴区域做成一个整体,让图表上下滚动。由于windows上左右滚动很不好用,所以水平方向上没有做滚动,而是设置了漫游器进行滚动以及缩放的功能。

数据流向
未命名文件 (1).png | left | 604x316

组件的数据流向很简单,用户传入初始化配置以及真实数据。大部分组件只是单纯负责渲染,只有漫游器会修改图表位置以及缩放的比例。然后图表和X轴会相应的显示对应区域。

结构和数据流向设计好,编码开发其实很简单了,不详述,自己看github上的代码吧。然后就是一些细节的打磨。

细节打磨

自己从头写的好处就是一些小细节可以打磨的舒服些

名字滑动吸左

滑动过程中节点名字吸左显示。

getTop.gif | left | 644x304

X轴放置不下隐藏

超出一定的比例之后按单双数隐藏了X轴的部分显示。其实既可以选择隐藏,也可以旋转一定的角度,自己做,随便定~

chaochang.gif | left | 776x120

漫游器防抖

antv和echart漫游器都是会抖动的,而且可拖拽区域都是只在漫游器内部。虽然echarts做了动画的优化,其实还是不太舒服。截个antv的效果好了。

doudong (1).gif | left | 611x253

我把漫游器设计成百分比的,所以滑动顺滑,而且滑动的时候事件加到了document上,可拖拽区域就变成整个页面了。

doudong (2).gif | left | 690x306

编码做完了,细节也打磨的差不多了。对于产品的可用性已经可以交差了。也get了svg画图的技能,可是,沉淀下了啥呢....别人会需要绘制一模一样的图么?感觉不太可能。仔细一想,自己做的东西复用性太差。那么问题来了,复用性差跟白做了有什么区别..

很欣赏<黑客与画家>里的一句话,“编程就跟画油画一样,永远没有完工的那一天,你只是不再画下去了而已”

复用性

在工程方面,可能复用性是自己一直以来比较忽视的点。但是其实思考复用性方面的问题,既是对你的设计以及代码质量的考验,也能为后续的工作提高效率。还能培养你面对问题的直觉,思考复用性其实就是在思考问题的共性。这一个个共性就是一个个点,一个个的点多了,你的知识结构才能被串联起来,形成一张网。

定义场景

如何提高复用性呢?首先明确定义业务使用场景:这个图是为了做时间基线上的任务耗时管理,并且能够与过往耗时进行对比。至少让别人在相同需求的时候能够复用,但是能重用的可能性太小了,不行。

二次开发

要不我降低二次开发的门槛?如果别人就想改一点图表的渲染,我是不是该支持定制化渲染。仔细想想感觉不用。因为图形绘制都改了,那离重画一张图也没啥区别,毕竟技术难度也算很高。为了增加这一点灵活性,要给组件加太多的复杂度了,而且拍脑袋决定哪里开放绘制肯定做不好。毕竟灵活性和复杂度是成正比的。为了得到一些的灵活性而需要付出的代价是非常需要权衡的。二次开发这样的事情交给antV来做更好。

抽象通用能力

那怎么办?再看看能不能抽象出有一些复杂度的可重用的部分。重新审视整个设计,可用性较强的是漫游器组件。也就是下图内红色虚线框的位置:

未命名文件 (3).png | left | 659x402

共用性的理由也很充分,毕竟windows上左右拖拽不方便是事实,图表配上漫游器是正常的能力,而且echarts和antv,漫游器都没有单独提供。

想明白了,做其实并不难。花些时间将漫游器的业务逻辑摘干净。将依赖全部以参数方式注入。然后定义好对外的接口,想想如何降低使用者的门槛。这个过程其实很能提高你的代码质量。你会抱怨自己为什么最开始写的时候没有解耦他们。可能更好的方式不应该是做完了之后进行抽象,而是设计阶段就能够意识到这是个通用能力而在设计层面就解耦掉。

具体的漫游器我也抽成了一个组件,如何使用可以参照我写在github上的demo。我抽成了几个装饰器和一个组件,感觉已经无力再抽了,如果有好的思路能够把他们合到一起的话欢迎告知我。

总结

文章主要是分享如何手工画一个自定义的图表,以及在这个过程中如何提高组件复用性来沉淀通用能力。更多的是分享下做业务组件应该去思考的角度,建议大家培养这样的习惯。毕竟习惯这种东西很可怕,我们可以先培养出一些习惯,然后等着习惯来推动你就好了。最后放上代码地址,图表地址漫游器地址

对我们团队感兴趣的可以关注专栏,关注github或者发送简历至'tao.qit####alibaba-inc.com'.replace('####', '@'),欢迎有志之士加入~

原文地址:github.com/ProtoTeam/b…

文章分类
前端