ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

react-vis BarSeries 完全指南:用 VerticalBarSeries / HorizontalBarSeries 构建柱状图与堆叠柱状图

react-vis BarSeries 完全指南:用 VerticalBarSeries / HorizontalBarSeries 构建柱状图与堆叠柱状图 数据可视化图表库前端【免费下载链接】react-visData Visualization Components项目地址https://gitcode.com/gh_mirrors/re/react-vis点击查看免费下载导读Bar Series柱状系列是 react-vis 中用于绘制矩形柱体的核心系列组件适合把「类别 → 数值」这类数据映射可视化出来。本文围绕仓库中的 bar-series.md 展开完整覆盖数据格式、系列级 API、交互事件处理器、barWidth 与 cluster 等关键配置并结合源码如 bar-series.js、series-utils.js与测试用例bar-series.test.js深入讲解其渲染原理。读完后你将能独立实现普通柱状图、水平柱状图、分组簇柱状图、堆叠柱状图以及差值图并为每根柱子挂接点击、悬停、右键等交互。注意该库已进入弃用deprecated状态具体说明见 DEPRECATED.md本文内容以当前仓库实际代码为准。一、什么是 Bar Series适用场景与选型TLDR用 bar series 画柱状图但别用它画直方图histogram。Bar series 允许用户构造包含矩形的图表这些矩形既可以「左右延伸」也可以「上下延伸」。这类系列通常用来可视化类别数据categorical到定量数据quantitative的映射。例如统计每个季节观测到的鸽子数量[{x: winter, y: 10}, {x: spring, y: 100}, {x: summer, y: 10000}, {x: fall, y: 10}]这就是典型的 bar series 使用场景。而如果你的数据是逐条观测记录例如[{x: May 1st 2pm}, {x: May 12th 1am}]那么请改用其他系列mark-series散点图展示离散的观测点rect-series直方图按数值区间聚合后展示分布。这个选择背后有实现层面的原因bar series 把 x或 y当作「类别」处理精确的左右位置并不重要条形只是落在对应的桶bucket内而直方图需要精确的区间边界这属于 rect-series 的职责范围。两种风味VerticalBarSeries 与 HorizontalBarSeriesBar series 有两种形态VerticalBarSeries竖着的柱子垂直柱状图HorizontalBarSeries横着的柱子水平柱状图。两者在 API 与数据格式上完全一致区别仅在于主轴/数值轴的朝向。从源码看二者都是对通用 BarSeries 的薄封装vertical-bar-series.js 传入linePosAttrx、valuePosAttry、lineSizeAttrwidth、valueSizeAttrheighthorizontal-bar-series.js 传入linePosAttry、valuePosAttrx、lineSizeAttrheight、valueSizeAttrwidth。也就是说「竖直/水平」只是把四个轴属性对调了一下线位置轴决定柱子落在哪个类别桶、线尺寸轴柱子的粗细、数值位置轴决定柱子从哪开始、数值尺寸轴柱子的长度。这也是两个系列都提供getParentConfigvertical-bar-series.js、horizontal-bar-series.js告知 XYPlot 需要调整域、以及从零开始绘制基线的根本原因。二、数据格式参考Data Format Reference与其他系列一样bar series 要求data是一个对象数组格式如下const myData [ {x: A, y: 10}, {x: B, y: 5}, {x: C, y: 15} ]其中x和y是必填的此外可以在每个数据点对象上自由附加额外属性例如用于getColor回调的字段。下面逐个说明数据字段的语义。x类型VerticalBarSeriesstring | number类型HorizontalBarSeriesnumber表示柱体所用的 x 坐标位置。在 VerticalBarSeries 中该值被当作**类别category**处理——这正是它接受字符串的原因——因此精确的左右位置并不重要如果需要精确数值定位应改用 rect-series。在 HorizontalBarSeries 中x 是数值轴会按比例缩放到像素。y类型VerticalBarSeriesnumber类型HorizontalBarSeriesstring | number表示柱体所用的 y 坐标位置。对于 VerticalBarSeriesy 被视为数值并按比例映射为像素柱子高度对于 HorizontalBarSeriesy 则充当类别对应yTypeordinal的用法见下文测试佐证。y0可选类型VerticalBarSeriesnumber类型HorizontalBarSeriesstring | number表示柱体底部的 y 坐标位置即柱子从哪里开始画默认为 0。不建议与堆叠stackBy柱状图混用。在差值图difference chart场景中y0 与 y 配合可以表达正负双向的柱体——详见本文「差值图」一节。color可选类型string | number单根柱子的颜色。默认情况下 color 被解释为数值并缩放到某个颜色范围要直接使用字面颜色值需要给系列传入colorTypeliteral。该属性也可以在系列series级别定义会被数据级覆盖。opacity可选类型number | Object单根柱子的不透明度。默认按literal缩放即直接使用提供的值。也可以在系列级别定义。stroke可选类型number | Object柱体描边轮廓颜色。未提供时回退使用 color 属性。也可以在系列级别定义。fill可选类型number | Object柱体内部填充颜色。未提供时回退使用 color 属性。也可以在系列级别定义。源码佐证在 bar-series.js 中填充与描边的 functor 正是按「优先 fill/stroke回退 color」的方式获取的this._getAttributeFunctor(fill) || this._getAttributeFunctor(color)。三、系列 API 参考Series API Reference以下是 bar series 在系列级别支持的属性。除了下列专用项它还继承 AbstractSeries 的通用属性如xType、yType、各属性的 range/domain 配置等。animation可选开启动画。具体配置请参见 XYPlot 文档中的animation一节。实现上bar-series.js 会检测到animation属性后用 animation.js 包裹自身并传入ANIMATED_SERIES_PROPS见 series-utils.js实现系列几何属性的平滑过渡。color类型string | number整个系列所有元素的颜色。会被数据中指定的 color 覆盖。参见 colors.md。className可选类型string为系列附加一个额外的 CSS 类名。实现上会与预置类rv-xy-plot__series rv-xy-plot__series--bar合并bar-series.js合并逻辑见 styling-utils.js 的getCombinedClassName。cluster为系列提供一个聚类键clustering key。与stackBy配合使用时可以生成「聚类堆叠柱状图」clustered stacked bar chart。回到之前的鸽子例子如果你有多个年份、按季节统计的鸽子数量并想逐年对比聚类就是很好的方案。详见本文「聚类 堆叠」一节。data类型ArrayObject系列的数据数组格式见上文「数据格式参考」。当data为空或null时bar-series.js 直接返回null不渲染任何内容测试用例No data也验证了这一行为。fill类型string | number整个系列所有元素的内部填充色。会被数据中的 fill 覆盖。参见 colors.md。opacity类型string | number整个系列所有元素的不透明度。会被数据中指定的值覆盖。stroke类型string | number整个系列所有元素的外侧描边色。会被数据中的 stroke 覆盖。参见 colors.md。style类型object一组 CSS 属性用于在显式属性之外定制系列样式。注意它会覆盖所有其他属性即 fill、stroke、opacity、color。参见 style.md。实现上它被展开在每条rect的 style 对象末尾bar-series.js因此具有最高优先级。barWidth类型Number默认值0.85每根柱子填充其「桶」空间的百分比。1.0表示柱子完全填满整个桶柱间无空隙更小的百分比则意味着柱与柱之间留有更多空白。默认值来自 bar-series.js 的defaultProps。其几何意义体现在渲染逻辑中halfSpace (distance / 2) * barWidthbar-series.jsdistance是类别轴上的刻度间距因此柱子的实际宽度 刻度间距 × barWidth。四、从零实现一个柱状图把上面几个 API 组合起来就是最基础的柱状图。参考仓库中的 bar-chart.js下面是可直接运行的示例import React from react; import { XYPlot, XAxis, YAxis, VerticalGridLines, HorizontalGridLines, VerticalBarSeries, LabelSeries } from react-vis; const greenData [ {x: A, y: 10}, {x: B, y: 5}, {x: C, y: 15} ]; const blueData [ {x: A, y: 12}, {x: B, y: 2}, {x: C, y: 11} ]; const labelData greenData.map((d, idx) ({ x: d.x, y: Math.max(greenData[idx].y, blueData[idx].y) })); export default function App() { return ( XYPlot xTypeordinal width{300} height{300} xDistance{100} VerticalGridLines / HorizontalGridLines / XAxis / YAxis / VerticalBarSeries classNamevertical-bar-series-example data{greenData} / VerticalBarSeries data{blueData} / LabelSeries data{labelData} getLabel{d d.x} / /XYPlot ); }要点解读xTypeordinal把 x 轴声明为顺序类别轴这是类别柱状图的标配多个VerticalBarSeries并列渲染时react-vis 会自动按同类别把柱子分组错开形成「簇状分组柱状图」见BarChart测试中 6 根rect的断言bar-series.test.jsLabelSeries用来在柱顶打标签getLabel返回要显示的文本className会被合并进rv-xy-plot__series--bar预置类方便你针对该系列写 CSS。水平柱状图把坐标对调水平柱状图只是把「类别」放到 y 轴、「数值」放到 x 轴。测试用例Ordinal Y-Axis HorizontalBarSeriesbar-series.test.js展示了标准写法XYPlot width{300} height{300} yTypeordinal HorizontalBarSeries data{[ {y: a, x: 10}, {y: b, x: 5}, {y: c, x: 15} ]} / /XYPlot这里yTypeordinal将 y 声明为类别轴数据中y为字符串类别、x为数值——与「数据格式参考」中 HorizontalBarSeries 的 x/y 类型约定完全对应。五、堆叠柱状图stackBy堆叠是把多个系列在同一类别桶内上下或左右拼接。核心是在XYPlot 上声明stackBy垂直柱状图stackByy示例见 stacked-vertical-bar-chart.js水平柱状图stackByx示例见 stacked-horizontal-bar-chart.js。垂直堆叠示例XYPlot width{300} height{300} stackByy VerticalGridLines / HorizontalGridLines / XAxis / YAxis / VerticalBarSeries data{[ {x: 2, y: 10}, {x: 4, y: 5}, {x: 5, y: 15} ]} / VerticalBarSeries data{[ {x: 2, y: 12}, {x: 4, y: 2}, {x: 5, y: 11} ]} / /XYPlot堆叠的关键逻辑在 series-utils.js 的getStackParams当_stackBy valuePosAttr即堆叠轴与数值轴一致且没有cluster时强制sameTypeTotal 1、sameTypeIndex 0让多个系列的柱子严格对齐、逐段累加而不是横向错开。六、聚类 堆叠clustered stacked bar chart仅使用stackBy只能得到一个「单一堆叠」若想同时表达「多个堆叠组」例如不同年份、同一组内不同水果就给每个系列加cluster属性为它提供聚类键。完整示例见 clustered-stacked-bar-chart.jsXYPlot classNameclustered-stacked-bar-chart-example xTypeordinal stackByy width{300} height{300} VerticalBarSeries cluster2015 color#12939A data{[ {x: Q1, y: 10}, {x: Q2, y: 5}, {x: Q3, y: 15}, {x: Q4, y: 20} ]} / VerticalBarSeries cluster2015 color#79C7E3 data{[ {x: Q1, y: 3}, {x: Q2, y: 7}, {x: Q3, y: 2}, {x: Q4, y: 1} ]} / VerticalBarSeries cluster2016 color#12939A data{[ {x: Q1, y: 3}, {x: Q2, y: 8}, {x: Q3, y: 11}, {x: Q4, y: 19} ]} / VerticalBarSeries cluster2016 color#79C7E3 data{[ {x: Q1, y: 22}, {x: Q2, y: 2}, {x: Q3, y: 22}, {x: Q4, y: 18} ]} / /XYPlot在该示例中2015 与 2016 是两个聚类组同一组内的两个系列按 y 堆叠。测试断言bar-series.test.js显示该图共渲染 4 个系列、16 根rect2 个年份 × 2 个堆叠系列 × 4 个季度。实现原理getSeriesPropsFromChildren会收集每个系列的cluster键并排序去重series-utils.js然后通过props.clusters.indexOf(child.props.cluster)计算出sameTypeIndex、用聚类数量作为sameTypeTotal。随后 bar-series.js 按照spacePerBar totalSpaceAvailable / sameTypeTotal - (sameTypeTotal - 1) / sameTypeTotal的公式在类别桶内把同聚类的系列错开排列而堆叠方向仍由getStackParams控制。七、差值图Difference Chart活用 y0当你想展示「正负双向」的柱子例如同比增减、预算与实际差额可以用y0指定每根柱子的起点。仓库中的 difference-chart.js 是一个完整范例const myDATA [...new Array(15)].map((x, idx) ({ x: idx, // 若柱子落在零线以下则从 idx - 4 开始画 y0: idx - 4 0 ? idx - 4 : 0, // 若柱子落在零线以上则止于 |idx - 4| y: idx 5 ? 0 : Math.abs(idx - 4) })); const yDomain myDATA.reduce( (res, row) ({ max: Math.max(res.max, row.y, row.y0), min: Math.min(res.min, row.y, row.y0) }), {max: -Infinity, min: Infinity} ); // ... XYPlot width{300} height{300} yDomain{[yDomain.min, yDomain.max]} VerticalBarSeries classNamedifference-example data{myDATA} colorTypeliteral getColor{d { return d.y0 0 ? #EF5D28 : #1A3177; }} / XAxis / YAxis / /XYPlot几个值得注意的细节因为柱子的起点不再是统一的 0必须手动计算 yDomain并传给 XYPlot否则超出/不足的部分可能被裁切colorTypeliteral让getColor直接返回颜色字符串而不是映射到颜色范围渲染端bar-series.js用Math.min(value0Functor(d), valueFunctor(d))作为柱顶起点、Math.abs(value0Functor(d) - valueFunctor(d))作为柱长从而天然支持「从负值画到正值」的任意区间。注意原文档明确提示 y0不建议与堆叠柱状图混用差值图场景请保持每个系列独立。八、交互事件处理器Interaction HandlersBar series 继承自 AbstractSeries 的全部事件处理器分为「值级」单根柱子与「系列级」整个系列两类。值级回调的接线见 bar-series.js每个rect上分别绑定onClick、onContextMenu、onMouseOver、onMouseOut分别转发给_valueClickHandler、_valueRightClickHandler、_valueMouseOverHandler、_valueMouseOutHandler。onNearestX可选类型function(value, {event, innerX, index})鼠标每次移动时触发的回调能够访问 x 位置最接近光标的那个数据点。两个参数value是数据点info对象包含innerX该柱子的左边缘位置index该数据点在数据数组中的下标event事件对象。实现见 abstract-series.js遍历data取|光标x - 柱子x|最小的数据点触发回调。参见 interaction.md。onNearestXY可选类型function(value, {event, innerX, innerY, index})鼠标移动时触发能够访问位置x 与 y 同时最接近光标的数据点。info对象包含innerX柱子的左边缘位置innerY柱子的顶部位置index数据点下标event事件对象。实现使用 d3-voronoi 对数据点建立泰森多边形再对光标坐标做命中查找abstract-series.js。参见 interaction.md。系列级事件onSeriesClick / onSeriesMouseOut / onSeriesMouseOver / onSeriesRightClick类型function默认值无这四个处理器在用户点击、鼠标移出、移入、右键点击系列整体时触发仅提供对应的事件对象不传递具体数据点。示例BarSeries ... onSeriesClick{(event) { // 处理点击可通过 event 访问事件值 }} onSeriesMouseOver{(event) { // 鼠标移入系列 }} onSeriesMouseOut{(event) { // 鼠标移出系列 }} onSeriesRightClick{(event) { // 右键点击系列 }} /从 abstract-series.js 可以看到系列级处理器只接收{event}一个参数对象。值级事件onValueClick / onValueMouseOut / onValueMouseOver / onValueRightClick类型function默认值无这四个处理器在用户点击、鼠标移出、移入、右键点击某根柱子mark时触发回调携带两个参数对应的数据点与事件对象。示例BarSeries ... onValueClick{(datapoint, event) { // 点击某根柱子 }} onValueMouseOver{(datapoint, event) { // 鼠标进入某根柱子 }} onValueMouseOut{(datapoint, event) { // 鼠标离开某根柱子 }} onValueRightClick{(datapoint, event) { // 右键点击某根柱子 }} /实现上值级处理器与系列级处理器会同时触发abstract-series.js例如_valueClickHandler先调用onValueClick(d, {event})再调用onSeriesClick({event})。九、Canvas 渲染VerticalBarSeriesCanvas / HorizontalBarSeriesCanvas当柱状图数据量较大时可以切换到 Canvas 渲染。仓库提供了对应的 Canvas 实现vertical-bar-series-canvas.jshorizontal-bar-series-canvas.js在展示示例中两者通过一个useCanvasstate 切换如 bar-chart.jsconst BarSeries useCanvas ? VerticalBarSeriesCanvas : VerticalBarSeries;测试bar-series.test.js确认切换后 SVG 中的rect.rv-xy-plot__series--bar数量归零Canvas 元素.rv-xy-canvas canvas出现。API 与 SVG 版本保持一致同一份data与属性可直接复用。十、常见问题与注意事项类别轴必须声明 ordinal字符串类别出现在 x 轴VerticalBarSeries或 y 轴HorizontalBarSeries时记得在 XYPlot 上设置xTypeordinal或yTypeordinal否则字符串无法被数值比例尺解释。精确坐标请用 rect-seriesbar series 把位置当类别处理柱子在桶内居中绘制如果柱子位置需要严格对应数值坐标应改用 rect-series。barWidth 控制间隙想要柱间留白把barWidth调小默认 0.85设为1.0则柱体完全贴紧。y0 与 stackBy 不兼容差值图y0 自由指定起点与堆叠图不要混用否则堆叠累计逻辑与 y0 起点会发生冲突。差值图手动设置 yDomain使用 y0 后柱子的最小/最大值已不是 0务必显式计算并传入yDomain避免图形被裁切。style 优先级最高style会覆盖 fill、stroke、opacity、color 等所有显式属性组合使用时要留意覆盖顺序。动画依赖 XYPlot 配置animation属性与 XYPlot 的动画设置协同工作动画属性列表见 series-utils.js。延伸阅读XYPlot柱状图的容器组件负责坐标轴、网格线与域的计算scales-and-data.md理解 x/y 比例尺与 ordinal 类型colors.mdcolor/fill/stroke 的取值与字面量模式style.md系列级 CSS 定制interaction.mdonNearestX / onNearestXY 等交互机制展示示例bar-chart.js、stacked-vertical-bar-chart.js、stacked-horizontal-bar-chart.js、clustered-stacked-bar-chart.js、difference-chart.js。赞分享数据可视化图表库前端【免费下载链接】react-visData Visualization Components项目地址https://gitcode.com/gh_mirrors/re/react-vis点击查看免费下载相关推荐Chart.js柱状图进阶分组、堆叠与浮动柱状图终极指南Chart.js柱状图进阶分组、堆叠与浮动柱状图终极指南 Chart.js 是一个基于 HTML5 Canvas 的简单而强大的图表库它允许开发者轻松创建各图表库前端数据可视化Flet BarChartRodStackItem 详解用 Python 构建分组堆叠柱状图Flet BarChartRodStackItem 详解用 Python 构建分组堆叠柱状图 导读 BarChartRodStackItem 是 Flet 图前端跨平台桌面应用移动开发React Chart.js 2柱状图终极教程分组、堆叠与水平布局完全指南React Chart.js 2柱状图终极教程分组、堆叠与水平布局完全指南 React Chart.js 2是一个强大的图表库它让开发者能够轻松地在Reac前端图表库上一篇如何在3天内掌握南开大学毕业论文LaTeX排版2024极速入门指南下一篇TEKLauncher彻底革新ARK游戏管理的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表