一、什么是visx
visx 是用于 React 的富有表现力的底层可视化组件集合,结合了 d3 的强大功能来生成可视化,以及 React 更新 DOM 的诸多优势。
在 Airbnb 内部,visx 的目标是统一整个公司的可视化堆栈,在此过程中,创建了 visx 项目,从而有效的将 D3 的强大功能与 React 结合在一起。
目前,visx在 Github 上通过 MIT 协议开源,有超过 17.5k 的 star、0.7k 的 fork、2.2k 的项目依赖量、代码贡献者 150+,妥妥的前端优质开源项目。
二、为什么使用 visx
本质上,Visx 是 Airbnb 开发的一系列基于 React 的数据可视化工具。 Visx 代表可视化组件而并非可视化库,是基元或组件的集合,可以将它们混合在一起以根据项目的要求创建自定义可视化库。
尽管 Visx 构建于流行的 D3 可视化库之上,但它仍将 DOM 操作工作委托给 React 库,而 D3 主要用于计算。 这样做的好处是,它可以减少当两个库争夺 DOM 控制权时可能出现的潜在错误。
Visx 适合任何 React 应用程序,无论架构如何。 同时,采用纯 React,很容易学习。 此外,开发者始终可以从 Visx 工具箱导入所需的内容,从而保持代码库较小且高性能。最后,Visx 非常稳定可靠,在 Airbnb 内部经过了长久的验证。总结起来看,visx 具有以下典型优点。
2.1 较小的打包体积
为了保持较小的打包尺寸, visx 可以被分成多个包,开发者可以轻松实现按需加载。
visx 的目标只是创建一个组件库,开发者可以使用它来制作可重用的图表库或精美的自定义一次性图表,最终的 bundle 包的大小仅使用需要的包。
2.2 强大的图表库
不是图表库,当开发者开始使用可视化基元时,最终将构建自己的针对特定用例进行优化的图表库,开发者完全可控。
在幕后,visx 使用 d3 进行计算和数学运算。 如果开发者想要在 visx 之上创建自己的图表库,则可以轻松创建完全隐藏 d3 的组件 api。 这意味着开发团队可以像使用可重用的响应式组件一样轻松地创建图表。
混合两种思维模型来更新 DOM 从来都不是一个好方法,比如:将 d3 代码复制粘贴到 componentDidMount() 。 visx 组件集合可让开发者轻松构建自己的可重用可视化图表或库,而无需学习 d3,比如:enter()/exit()/update()等方法。
2.3 取消内置功能
visx 取消了内置功能, 允许开发者选择自己的状态管理、动画库或 CSS-in-JS 解决方案。
同时,visx 基于 React, 如果开发者了解 React 就可以很轻松的进行可视化, 使用相同的标准 API 和熟悉的模式。 visx 在任何 React 代码库中都能轻松集成。
2.4 visx vs 其他可视化库
据 Airbnb 工程团队介绍,Visx 的主要目标是性能、可学习性和表现力,这是一种非常罕见的组合,也是任何其他基于 React 的前端可视化库的短板。
虽然 D3 在 React 中构建富有表现力的可视化方面是老手,但它的学习曲线非常陡峭。 React 开发人员不能仅根据以前的 React 经验来启动并运行它。 还有其他可视化工具可以解决可学习性问题,例如: React-vis,但这是以牺牲表达性和性能为代价的。 因此,Visx 并不是 Airbnb 漫无目的的工程实力展示。 它实际上为构建可视化应用程序的 React 工程师解决了一个巨大的问题。
三、visx使用
首先,我们需要安装visx相关的包,安装的命令如下:
npm install --save @visx/mock-data @visx/group @visx/shape @visx/scale
接下来,我们通过下面的示例来简单的说明如何快速绘制图表:
import React from "react";
import { letterFrequency } from "@visx/mock-data";
import { Group } from "@visx/group";
import { Bar } from "@visx/shape";
import { scaleLinear, scaleBand } from "@visx/scale";
// 为此,使用来自“@visx/mock-data”的一些模拟数据。
const data = letterFrequency;
// 定义图形尺寸和边距
const width = 500;
const height = 500;
const margin = { top: 20, bottom: 20, left: 20, right: 20 };
// 创建一些边界
const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;
//将通过一些工具函数来获取想要的数据
const x = (d) => d.letter;
const y = (d) => +d.frequency * 100;
// 然后根据数据缩放图表
const xScale = scaleBand({
range: [0, xMax],
round: true,
domain: data.map(x),
padding: 0.4,
});
const yScale = scaleLinear({
range: [yMax, 0],
round: true,
domain: [0, Math.max(...data.map(y))],
});
// 将比例函数和访问器函数组合在一起以获得点函数
const compose = (scale, accessor) => (data) => scale(accessor(data));
const xPoint = compose(xScale, x);
const yPoint = compose(yScale, y);
// 最后我们将其全部嵌入到 SVG 中
function BarGraph(props) {
return (
<svg width={width} height={height}>
{data.map((d, i) => {
const barHeight = yMax - yPoint(d);
return (
<Group key={`bar-${i}`}>
<Bar
x={xPoint(d)}
y={yMax - barHeight}
height={barHeight}
width={xScale.bandwidth()}
fill="#fc2e1c"
/>
</Group>
);
})}
</svg>
);
}
// ... somewhere else, render it ...
// <BarGraph />
我们可以使用codesandbox在线开发和体验:codesandbox.io/s/github/ai…
参考资料:
github.com/airbnb/visx…
airbnb.io/visx/galler…
airbnb.io/visx/
blog.logrocket.com/introductio…
www.youtube.com/watch?v=wA_…
airbnb.io/visx/docsht…