软件开发架构师

2019 年值得推荐的 React 可视化库

前端 35 2019-05-24 15:28

最近我们在开发Cube.js时,调研了许多不同的可视化库。Cube.js 在兼容 SQL 语法的数据库之上构建用于分析的 API 层,因此任何图表库均能够和 Cube.js 一起用来构建仪表板。这就是为什么我们一直在寻找一个优质而且对于开发者更友好的可视化库。

以下的列表仅针对 React 专用库。我会尝试使用坐标轴、图例和工具提示来构建几乎一模一样的堆叠式的条形图。在数据后端方面,我们将使用 Heroku 托管的 Cube.js。我还会使用Cube.js 的 React 组件,它使用了render props技术,并且它只渲染自己,所以我们能通过任何图表库构建我们想要的任何东西。

在此期间,我还会使用 2 个非常好用的库,分别是 moment.js 和 numeral.js,它们分别用于日期和数字的格式化。

作为数据输入,我们还会使用来自 Cube.js Javascript 客户端的https://cube.dev/docs/@cubejs-client-core \l result-set-chart-pivot \t _blank">resultSet.chartPivot() 方法。它会返回一个数据数列,在我们的例子当中,它长这样:

复制代码
[
{
"x": "2017-01-01T00:00:00.000",
"completed, Orders.count": 208,
"processing, Orders.count": 252,
"shipped, Orders.count": 233
},
{
"x": "2017-02-01T00:00:00.000",
"completed, Orders.count": 188,
"processing, Orders.count": 209,
"shipped, Orders.count": 222
},
]

现在,让我们转向列表。

如果你没有发现你中意的库,或者想让我再添加一个库,请在这个 Slack 频道 ping 我。我非常乐意在列表中添加更多的库:

https://cubejs-community.herokuapp.com/

Recharts

http://recharts.org/

Recharts 提供了一组模块化的图表组件,并且能够让你将这些组件进行组合,从而轻易地构建许多东西,比如曲线条形组合图

它是我列出这几个里面最受欢迎的库。它在 Github 上有超过 11000 颗星,但同时也有大量的开启的 issue(迄今为止为 600 个)。

它的文档非常全面,但缺乏某些方面的细节。你可以在 Rechart’s 网站上 (http://recharts.org/) 找到一些例子,然后根据它们开始构建你自己的图表。

Recharts 针对定制提供了多样化的配置项。除此以外,它还允许通过定制化 SVG 元素进行低级别的定制。 下面就是怎样在 Recharts 中构建堆叠式条形图的方法:

在这个例子以及所有随后的例子中,我都使用了 colors、dateFormatter 和 numberFormatter 变量。下面展示了我是如何定义它们的:

复制代码
const numberFormatter = item => numeral( item).format( "0,0");
const dateFormatter = item => moment( item).format( "MMM YY");
const colors = [ "#7DB3FF", "#49457B", "#FF7C78"];
export default ({ resultSet, colors, dateFormatter, numberFormatter }) => (
<ResponsiveContainer width= "100%" height={ 300}>
<BarChart data={resultSet.chartPivot()}>
<XAxis tickFormatter={dateFormatter} dataKey= "x" />
<YAxis tickFormatter={numberFormatter} />
{resultSet.seriesNames().map((series, i) => (
<Bar
stackId= "a"
dataKey={series}
name={series.split( ",")[ 0]}
fill={colors[i]}
/>
))}
<Legend />
<Tooltip labelFormatter={dateFormatter} formatter={numberFormatter} />
</BarChart>
</ResponsiveContainer>
);

Demo 见:

https://codesandbox.io/embed/4j4jlz33z0?fontsize=14&initialpath=/recharts

Victory

https://formidable.com/open-source/victory/

Victory 使用了和 Recharts 相同的组合模式。

它是由Formidable开发的。除了 Victory 外,Formidable 还拥有其它可靠的开源库。它是列表中唯一一个能够兼容 React Native 的库。

Victory 是仅次于 Recharts 的第二受欢迎的库,在 Github 上有 7000 颗星,但是它的开启的 issue 只是 Recharts 的五分之一。Victory 在Spectrum 上有一个社区聊天群

它的文档化良好而且有一个示例陈列馆

Victory 提供了 2 个样式风格:灰度和 Material,并且能让你创建客户主题,从而使所有图表的外观保持一致。 下面,你可以看到我们堆叠式的条形图在 Victory 里面的代码。

复制代码
const transformResult = (series, resultSet) =>
resultSet.chartPivot(). map( element => ({ x: element.x, y: element[series] }));
export default ({ resultSet, dateFormatter, colors, numberFormatter }) => (
<div height={ 300}>
<VictoryChart
containerComponent={
<VictoryVoronoiContainer
voronoiDimension= "x"
labels={(d, i) => `${resultSet.seriesNames()[i]}: ${d.y}`}
labelComponent={
<VictoryTooltip cornerRadius={ 0} flyoutStyle={{ fill: "white" }} />
}
/>
}
domainPadding={{ x: 20, y: [ 0, 20] }}
>
<VictoryLegend
colorScale={colors}
data={resultSet.seriesNames().map(series => ({
name: series.split( ",")[ 0]
}))}
orientation= "horizontal"
y={ 275}
x={ 130}
/>
<VictoryAxis tickFormat={dateFormatter} tickCount={ 8} />
<VictoryAxis dependentAxis />
<VictoryStack colorScale={colors}>
{resultSet.seriesNames().map((series, i) => (
<VictoryBar key={i} data={transformResult(series, resultSet)} />
))}
</VictoryStack>
</VictoryChart>
</div>
);

Demo 见:

https://codesandbox.io/embed/4j4jlz33z0?fontsize=14&initialpath=/victory

Nivo

https://nivo.rocks/

同 Recharts 和 Victory 一样,Nivo 基于 D3 而且是 React 特有的。但与前面的库不同的是,它不支持图表组合。每个图表类型仅提供了一个组件,而且这个组件是通过多个 props 来配置的。Nivo 是针对特定的图表类型如 @nivo/bar 的一套程序包。所以,你需要安装特定的程序包,才能使用特定的图表类型。

该项目本身非常活跃。它在 Github 上有 5000 颗星,在社区聊天群中有 300 名成员。

它的文档非常互动化,你可以根据文档构建图表的配置。虽然它很好,但是它缺乏一个纯文本形式的 API 参考和搜索功能。此外,它还有一个带有示例的Storybook。它大大地缩减了我创建第一张表的时间。同 Victory 一样,Nivo 让你能够创建自己的主题,从而使所有图标的外观保持一致。

我们将在堆叠式的条形图中使用 @nivo/bar 包。你可以在下面找到代码示例和 CodeSandbox 的演示。

复制代码
//https://github.com/plouc/nivo/issues/138#issuecomment-373015114
const ticksFormmater = (ticksCount, value, data, dateFormatter) => {
const valueIndex = data.map( i => i.x).indexOf(value);
if (valueIndex % Math.floor(data.length / ticksCount) === 0) {
return dateFormatter(value);
}
return "";
};
export default ({ resultSet, colors, dateFormatter, numberFormatter }) => (
<div style={{ height: 300 }}>
<ResponsiveBar
enableLabel= {false}
colors= {colors}
data= {resultSet.chartPivot()}
keys= {resultSet.seriesNames()}
indexBy= "x"
enableGridY= {false}
padding= {0.3}
margin= {{ top: 60, right: 80, bottom: 60, left: 40 }}
axisLeft= {{
format: numberFormatter
}}
axisBottom= {{
format: value =>
ticksFormmater(8, value, resultSet.chartPivot(), dateFormatter)
}}
tooltip={({ id, value, color }) => (
<strong style={{ color }}>
{id.split(",")[0]}: {numberFormatter(value)}
</strong>
)}
legends={[
{
anchor: "bottom",
direction: "row",
translateY: 50,
itemsSpacing: 2,
itemWidth: 150,
itemHeight: 20,
itemDirection: "left-to-right"
}
]}
/>
</div>
);

Demo 见:

https://codesandbox.io/embed/4j4jlz33z0?fontsize=14&initialpath=/nivo

BizCharts

https://bizcharts.net/products/bizCharts

BizCharts 是一个基于G2的 React 特有的可视化库,G2 是一种可视化语法。BizCharts 由阿里巴巴支持,并且能够和 Ant Design 框架良好配合。

它在 Github 上约有 4000 颗星,但是大部分的开发仍是中文的,其文档也是如此。据我所知,该团队正在翻译这些文档,但是仍未完成所有的翻译。

虽然它欠缺英文文档,但是其 API 非常简单易懂。唯一的困难是你需要将数据格式转化成堆叠式图表特有的格式。

复制代码
const stackedChartData = resultSet => {
const data = resultSet
.pivot()
.map(({ xValues, yValuesArray }) =>
yValuesArray.map(([yValues, m]) => ({
x: resultSet.axisValuesString(xValues, ", "),
color: resultSet.axisValuesString(yValues, ", "),
measure: m && Number.parseFloat(m)
}))
)
.reduce((a, b) => a.concat(b));
return data;
};
export default ({ resultSet, dateFormatter, colors, numberFormatter }) => (
<Chart
scale={{ x: { tickCount: 10 } }}
height={ 400}
data={stackedChartData(resultSet)}
forceFit
>
<Axis name= "x" label={{ formatter: dateFormatter }} />
<Axis label={{ formatter: numberFormatter }} name= "measure" />
<Tooltip />
<Geom
type= "intervalStack"
position={`x*measure`}
color={[ "color", colors]}
/>
<Legend itemFormatter={item => item.split( ",")[ 0]} />
</Chart>
)}
/>
);

Demo 见:

https://codesandbox.io/embed/4j4jlz33z0?fontsize=14&initialpath=/bizcharts

React-vis

https://uber.github.io/react-vis/

React-vis 是由 Uber 开发的,而且目前在 Github 上有 5400 颗星、150 个开启的 issue,最近也有很多提交,因此它似乎非常活跃。它是模块化的,这点同列表中的大多数库一样。它还有许多非常棒的默认风格,这些风格必须单独以 CSS 文件的方式导入。

同 Nivo 一样,React-vis 也有带有示例的故事簿。其组件 API 的文档化也非常好。在定制方面,你可以通过定制的 CSS 风格来控制其外观和给人的感觉。React-vis 还提供了一个特别的组件即 CustomSVGSeries来构建定制的 SVG 图表。

其 API 和 Victory 的相似。下面,你可以看到,我使用了与 Victory 代码段几乎一模一样的 transformResult。

复制代码
const transformResult = (series, resultSet, dateFormatter) =>
resultSet
.chartPivot()
. map( element => ({ x: Date.parse(element.x), y: element[series] }));
export default ({ resultSet, dateFormatter, colors, numberFormatter }) => (
<XYPlot xType= "time" height={ 300} width={ 500} stackBy= "y">
<XAxis tickFormat={dateFormatter} tickSize={ 8} />
<YAxis />
{resultSet.seriesNames().map((series, i) => (
<VerticalBarSeries
cluster= "stack 1"
key={i}
color={colors[i]}
data={transformResult(series, resultSet, dateFormatter)}
/>
))}
<DiscreteColorLegend
colors={colors}
items={resultSet.seriesNames().map(i => i.split( ",")[ 0])}
orientation= "horizontal"
style={{ position: "absolute", left: 130, bottom: - 30 }}
/>
</XYPlot>
);

Demo 见:

https://codesandbox.io/embed/4j4jlz33z0?fontsize=14&initialpath=/react-vis

查看英文原文https://blog.statsbot.co/react-visualization-libraries-in-2019-91be49a01158

你喜欢的 React 可视化库是哪个呢?欢迎留言分享。

文章评论