资讯专栏INFORMATION COLUMN

组件化可视化图表 - Recharts

roland_reed / 2066人阅读

摘要:是年初团队可视化组推出的一款可视化组件库,为基础表格的绘制提供了另外一种可能。为方便国际化,文档只有英文官网,中文官网还在编写中。如果试用有问题,欢迎给项目提请使用英文来提,谢谢。

Recharts 是 2016 年初团队可视化组推出的一款可视化组件库,为基础表格的绘制提供了另外一种可能。

Recharts 含义是重新定义(Redefined)图表。这个名字的背后在于这个图表在设计上带给开发者的是不一样的体验,不仅是用 React 设计,也在于重新定义了组合与配置方式。

Recharts 到今天的版本是 0.9.3,支持 React 0.14.x 或 15.0.x 版本,现在有至少四个国外团队在产品中使用。为方便国际化,文档只有英文官网 Recharts,中文官网还在编写中。如果试用有问题,欢迎给项目提 issue(P.S. 请使用英文来提,谢谢)。

接下来我们会从思想层面来剖析 Recharts 的原理和精髓。

大家可以回顾一下在做图表类的需求时,碰到最纠结的问题是什么?这里列了一些我碰到最多的问题:

配置非常复杂,可配置的内容太多,找不到到底使用什么配置项来达到想要的目的

很多样式无法完全统一,变化很多。这个线图怎么多了条线?这个柱图的“柱子”怎么是个三角形?

那 Recharts 是怎么解决这些问题呢?

声明式的标签,让写图表和写 HTML 一样简单

贴近原生 SVG 的配置项,让配置项更加自然

接口式的 API,解决各种个性化的需求

下面我们将仔细分析这些是怎么实现的。

声明式的标签

在看代码实现之前,我们先看看怎样一步步的根据各自的需求创建一个线图:

首先,通过调用 LineChart 添加一条 dataKeypvLine

const data = [{ name: "a", uv: 4000, pv: 2400 }, { name: "b", uv: 3000, pv: 1398 }, ....];


  

运行代码后结果如下:

然后,我们可以根据自己的需求去丰富这个线图,比如这个线图需要一个 X 轴和 Y 轴,那只需要在 LineChart 下添加一个 XAxisYAxis 标签即可:

const data = [{ name: "a", uv: 4000, pv: 2400 }, { name: "b", uv: 3000, pv: 1398 }, ....];


  
  
  

运行代码结果如下:

大家看到用 Recharts 绘制图表很多时候就想拼积木一样,那 LineChart 内部是如何去识别这些『零件』的呢?我们先来看一个简单的函数:

const getDisplayName = (Comp) => {
  if (!Comp) { return ""; }
  if (typeof Comp === "string") { return Comp; }
  return Comp.displayName || Comp.name || "Component";
};

这个方法很简单,可以用来读取某个 ReactComponent 的名称。在 LineChart 的代码实现中,就是根据 ReactComponent 的 displayName 来识别所有的 Children。我们先来看一个工具方法:

const findAllByType = (children, type) => {
  const result = [];
  let types = [];

  if (_.isArray(type)) {
    types = type.map(t => getDisplayName(t));
  } else {
    types = [getDisplayName(type)];
  }

  React.Children.forEach(children, child => {
    const childType = child && child.type && (child.type.displayName || child.type.name);
    if (types.indexOf(childType) !== -1) {
      result.push(child);
    }
  });

  return result;
};

这里 type 可以是 ReactComponent 或者 ReactComponent 数组。而 LineChart 内部实现的时候就是调用这个方法来识别各个『零件』:

    ...
    render() {
        const { children } = this.props;
        const lineItems = findAllByType(children, Line);
        ...
    }
贴近原生的配置项

图表的配置项可以非常多,但是有很多配置项如填充颜色、描边颜色、描边宽度等等这些都是SVG标签原生就支持的属性,为了减小大家的配置的成本,Recharts 的组件会去解析原生的属性。举个例子,一个线图里面有两条曲线,我想给一条曲线设置成虚线,一条设置成实线,我们只需要像原生的 SVG 元素一样设置 stroke-dasharray 属性就行:

const data = [{ name: "a", uv: 4000, pv: 2400 }, { name: "b", uv: 3000, pv: 1398 }, ....];


  
  
  
  

结果如下:

实现原理也比较简单,首先 Recharts 内部维护一份 SVG 元素支持的所有属性,然后在渲染 SVG 元素之前,我们会去解析相应的ReactElement的 props,看看哪些是 SVG 元素能够支持的属性,最终这些属性可以传入到渲染的 SVG 元素中。

const PRESENTATION_ATTRIBUTES = {
    fill: PropTypes.string,
    strokeDasharray: PropTypes.string,
    ...
};
const getPresentationAttributes = (el) => {
  if (!el || _.isFunction(el)) { return null; }

  const props = React.isValidElement(el) ? el.props : el;
  let result = null;

  for (const key in props) {
    if (props.hasOwnProperty(key) && PRESENTATION_ATTRIBUTES[key]) {
      if (!result) {result = {};}
      result[key] = props[key];
    }
  }

  return result;
};

关于更多SVG属性,大家可以参考W3C标准文档

接口式的 API

很多时基础图表往往不能满足所有的要求,那怎么去满足各种个性化的需求成了图表组件必须要考虑的事情。

Recharts 对可能会变化的元素都提供了自定义的接口,以x轴的刻度为例,普通的刻度就是一些文字,在信息图表中,为了让图表更佳的生动,视觉往往希望能够将文字替换成形象的 icon。

对于这种自定义的需求,Recharts 提供了两种方式,第一种是通过 React Element 的方式:

const CustomizedTick = (props) => {
  const { x, y, payload, bgColor, index } = props;

  return (
      
          
      {index}
    
  );
};


  }/>
  
  
  

通过将 tick 设置成一个 React Element,在拿到内部 props 的同时,也可以非常方便的从外部传入 props

第二种自定义的方式是通过 function:

const renderCustomizedTick = (props) => {
  const { x, y, payload, index } = props;

  return (
      
          
      {index}
    
  );
};


  
  
  
  

这种方法,renderCustomizedTick 中拿到的参数和 CustomizedTickprops 是一样的,当然这种自定义的方法外部传参数会稍微麻烦一些。

看到这里大家可能会好奇内部是怎么去实现?原理也非常简单,我们在内部计算好 tick 的位置等信息,然后判读 tick 参数的类型,实现代码简化如下:

let tickItem;

if (React.isValidElement(tick)) {
  tickItem = React.cloneElement(tick, props);
} else if (_.isFunction(tick)) {
  tickItem = tick(props);
} else {
  tickItem = {value};
}

看到这里大家可以发现 Recharts 内部主要做了计算各种 layout 的事,每个区块具体展示什么内容都是可以自定义的。

延伸

到这里我们已经介绍了 Recharts 实现可视化组件的一些核心思想,其实这些思想不只是在可视化组件中可以应用,很多组件也可以考虑利用这种思想来实现,例如表格组件就可以抽取 TableColumn 两个组件,然后大家使用表格也非常简单:


  }/>
  
关于 1.0 版本的发布

我们大约会在本月末,或下月初发布,

更好的动画支持

同步文档更新

增加一些图表的支持

90% 的测试覆盖率

关于无线支持可能会放到 1.0 之后再考虑,因为 SVG 对手机的兼容性支持度一般。1.0 版本之后,会切分出 React 15.x 的 Recharts。因为 15.x 对 SVG 的支持更加完善。

尽管 web 端已经有不少优秀的可视化库,亦或是图表库,比如 Echarts,highcharts,科学界有 ggplot,他们都是可视化界的前辈。在可视化的探索上,给我们很多启发。我们造 Recharts 的初忠是给 React 社区贡献一个代码更优雅,灵活可装卸的图表库的图表库。

感谢团队可视化组的小伙伴。最后是安利时间,第一款使用 Recharts 的线上项目 阿里指数。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79250.html

相关文章

  • 前端开发者常用的9个JavaScript图表

    摘要:使用来呈现图表。允许用户在应用程序中创建美观的可复用的图表。它是基于创建的,是一个以数据为中心的图表库,可以改进数据可视化的效果。非常轻巧,并使用元素来创建很奇特的图表。是库中较为古老的图表库之一。总结以上介绍的库都是高质量的图表库。 当前,数据可视化已经成为数据科学领域非常重要的一部分。不同网络系统中产生的数据,都需要经过适当的可视化处理,以便更好的呈现给用户读取和分析。 对任何一个...

    luck 评论0 收藏0
  • 14个最好的 JavaScript 数据视化

    摘要:适用于,演示这是开发的一个简单的可视化库,它允许你创建所有常用的图表类型条形图,树形图,折线图,面积图等。可以轻松地对折线图和条形图进行混合和匹配以组合不同的数据集,这是非常棒的功能。 翻译:疯狂的技术宅原文:https://www.monterail.com/blo... 本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章 你的程序有多...

    Mertens 评论0 收藏0
  • 11个React Native 组件库和 Javascript 数据视化

    摘要:数据可视化库超过的的可能是最流行和最广泛的数据可视化库。是一组组件,用于高效地渲染大型列表和表格数据。一种优雅而灵活的方式,可以利用组件来支持实际的数据可视化。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! React Native 组件库 1. NativeBase showImg(https://segmentfault.com/img/bVbrLHH?w=...

    tangr206 评论0 收藏0
  • 基于Decorator的组件扩展实践

    摘要:在业务统一的情况下,仅仅修改组件用于配置的就可以满足业务需求。避免了复杂的图表配置,而将图表进行有效拆分,通过声明式的标签进行组合,从而使图表更具扩展性。而对于颗粒度最细的组件,我们希望它是纯粹的,木偶式的组件。 在前端业务开发中,组件化已经成为我们的共识。沉淀和复用组件,是提高开发效率的利器。但在组件复用的过程中,我们往往会遇到这样的问题,组件相似,却在结构或交互上有些许差别,需要对...

    魏明 评论0 收藏0
  • GitHub 值得收藏的前端项目[每月更新...]

    摘要:也是一款优秀的响应式框架站点所使用的一套框架为微信服务量身设计的一套框架一组很小的,响应式的组件,你可以在网页的项目上到处使用一个可定制的文件,使浏览器呈现的所有元素,更一致和符合现代标准。 GitHub 值得收藏的前端项目 整理与收集的一些比较优秀github项目,方便自己阅读,顺便分享出来,大家一起学习,本篇文章会持续更新,版权归原作者所有。欢迎github star与fork 预...

    maxmin 评论0 收藏0

发表评论

0条评论

roland_reed

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<