开源一个 React 股票 K 线图组件,传个股票代码就能画图

前端做金融图表的坑,我替你踩过了。

背景

说来话长,但我尽量说短。

某天产品跑过来跟我说:"在页面上加个 K 线图吧,应该不难。"

我当时心想,2025 年了,这东西还需要自己写?npm 上肯定一堆现成的。

结果我打开 npm 搜了一圈,发现情况不太乐观:

  • 有些组件功能倒是全,但那是人家商业产品,开源版阉割得差不多了,想用完整功能得掏钱
  • 有些看起来还行,点进去一看,最后一次 commit 是两年前,依赖的 React 版本还停留在 16
  • 还有一些纯 Canvas 手撸的,佩服是佩服,但接入成本太高,文档还是英文半成品

纠结了一下午,我决定自己写一个。

直接看东西

项目叫 kline-charts-react,已经发到 npm 上了。

GitHub | npm | 在线演示

最简单的用法,五行代码搞定:

tsx 复制代码
import { KLineChart } from 'kline-charts-react';
import 'kline-charts-react/style.css';

function App() {
  return <KLineChart symbol="sh600519" height={600} />;
}

没错,一个 symbol 属性就完事了。数据获取、指标计算、图表渲染,组件内部全包了。

"那数据是从哪来的?不会要我自己对接接口吧?"

不需要,往下看。

功能概览

目标是做到雪球 K 线图那种体验。目前做到了大概八成:

多周期:分时走势、五日分时、日 K、周 K、月 K,还有 1 分钟到 60 分钟的分钟线。炒短线的朋友可以放心了。

技术指标:支持 15 种 ------ MA、BOLL、MACD、KDJ、RSI、WR、BIAS、CCI、ATR、OBV、ROC、DMI、SAR、KC。所有指标都在浏览器端计算,不需要服务端返回。说实话,写这些计算公式的过程挺上头的,特别是 DMI 和 SAR,逻辑绕得我差点怀疑人生。

交互体验:滚轮缩放、拖拽平移、十字准线跟随、Tooltip 信息展示、缩放的撤销/重做、一键全屏、导出 PNG 图片。

外观:浅色和深色两套内置主题,也可以传自定义的颜色配置进去。

复权支持:不复权、前复权、后复权三种模式可切换,默认前复权。

数据层 ------ 聊聊 stock-sdk

做图表组件,绑定什么数据源是个问题。

前端圈搞股票数据一直比较尴尬 ------ 好用的库几乎全是 Python 的。tushare、akshare、baostock,想用的话你得起个 Python 服务,前端再请求这个服务。链路长,维护烦。

为了解决这个痛点,我做了 stock-sdk,一个纯前端/Node.js 的股票行情 SDK。

核心思路就一句话:前端工程师获取股票数据,不应该需要 Python。

stock-sdk 的几个亮点:

  • 零依赖、体积小,TypeScript 写的,打包压缩后不到 20KB
  • 浏览器和 Node.js 都行,ESM 和 CJS 双格式输出
  • 覆盖面广,A 股、港股、美股、公募基金,实时行情和历史 K 线都能取
  • 自带指标计算,MA、MACD、BOLL、KDJ、RSI 等主流技术指标直接调用
  • 类型提示完善,TS 项目用起来体验很好,字段名不用猜

简单示意:

ts 复制代码
import { StockSDK } from 'stock-sdk';

const sdk = new StockSDK();

// 拉几只股票的实时报价
const quotes = await sdk.getSimpleQuotes(['sh600519', 'sz000858']);
quotes.forEach(q => {
  console.log(`${q.name}: ${q.price} (${q.changePercent}%)`);
});

// 拉日 K 线数据
const kline = await sdk.getKline('sh600519', { period: 'daily', adjust: 'qfq' });

kline-charts-react 底层就集成了 stock-sdk,传一个股票代码进去,组件会自动请求数据、计算指标、渲染图表,整条链路在浏览器端闭环,不依赖任何后端服务。

stock-sdk 本身也是独立的 npm 包,不画图的场景一样能用 ------ 做个行情 Dashboard、写个 Node 定时任务抓数据之类的,都没问题。

更多用法参考官方文档:stock-sdk.linkdiary.cn

当然了,如果你们公司有现成的行情接口,组件也支持自定义数据源,完全可以绕过 stock-sdk。

技术选型

图表渲染这块我选了 ECharts。

有人可能觉得 ECharts 太重了,但实际上组件里用了按需引入 ------ 只注册了 CandlestickChart、LineChart、BarChart、ScatterChart 这几个模块,并不是把整个 ECharts 都打进去。

而且 ECharts 的优势很明显:渲染性能好、交互事件体系成熟、响应式适配开箱即用。自己从 Canvas 开始画当然也行,但工期不允许。

关于包体积,组件自身(不含 echarts 和 react)构建产物 77KB ,gzip 后约 19KB。echarts 走 peerDependency,项目里已有的话不会重复打包。

设计上的一些考量

1. 开箱即用 vs 高度可配

默认情况下传个 symbol 就能渲染,零配置。但所有细节都暴露了 props:

tsx 复制代码
<KLineChart
  symbol="sh600519"
  period="weekly"
  adjust="qfq"
  theme="dark"
  indicators={['ma', 'volume', 'kdj', 'rsi']}
  indicatorOptions={{
    ma: { periods: [5, 10, 20, 60] },
  }}
  maxSubPanes={3}
  height={700}
/>

想用哪些指标、均线取几日、副图显示几个、用什么主题,随便调。

2. 自定义数据源

如果你有自己的行情 API,通过 dataProvider 可以完全替换内置的数据获取逻辑:

tsx 复制代码
const myProvider = {
  getKline: async (params, signal) => {
    const res = await fetch(`/api/kline?symbol=${params.symbol}&period=${params.period}`, { signal });
    return res.json();
  },
  getTimeline: async (params, signal) => {
    const res = await fetch(`/api/timeline?symbol=${params.symbol}`, { signal });
    return res.json();
  },
};

<KLineChart symbol="sh600519" dataProvider={myProvider} />

数据结构很直观 ------ K 线是 { date, open, close, high, low, volume, amount },分时是 { time, price, volume, amount, avgPrice }。传进来原始数据就行,MA、MACD 这些指标组件内部会自己算。

3. 外部控制

通过 ref 可以在组件外部调用方法,适合需要和外部 UI 联动的场景:

tsx 复制代码
const chartRef = useRef<KLineChartRef>(null);

// 手动刷新
chartRef.current?.refresh();

// 导出成图片
const dataUrl = chartRef.current?.exportImage('png');

// 程序化切换到周 K
chartRef.current?.setPeriod('weekly');

// 拿到底层 ECharts 实例
const instance = chartRef.current?.getEchartsInstance();

4. 分时自动刷新

盯盘场景下,分时图需要定时刷新。组件内置了轮询机制,还支持限制只在交易时段刷新:

tsx 复制代码
<KLineChart
  symbol="sh600519"
  period="timeline"
  autoRefresh={{ intervalMs: 5000, onlyTradingTime: true }}
/>

安装方式

bash 复制代码
yarn add kline-charts-react

# peer dependencies 也别忘了装
yarn add react react-dom echarts

echarts 是 peerDependency,你项目里已经有的话就不用重复安装了。

还有哪些不足

几个目前没做好的地方,先摆出来:

  • 手机端:触屏的捏合缩放、双指拖动这些还没有专门适配
  • 图片导出:导出的图片不包含左上角的指标数值标签(那部分是 DOM 元素,不在 Canvas 上)
  • WebSocket:暂时只有轮询,还没对接实时推送

这些都在计划中,后面会陆续补上。

写在最后

本来只是想解决手头的需求,没想到越写越多,最后索性做成了一个完整的组件库发了出来。

如果你正好有在 React 项目中展示 K 线图的需求,不妨装上试试。遇到问题欢迎在 GitHub 提 issue,PR 更好。

顺手点个 Star 就更好了,我写那些技术指标公式真的掉了不少头发。


相关推荐
不爱说话郭德纲2 小时前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
大雨还洅下2 小时前
前端JS: 虚拟dom是什么? 原理? 优缺点?
javascript
唐叔在学习2 小时前
[前端特效] 左滑显示按钮的实现介绍
前端·javascript
用户5282290301803 小时前
【学习笔记】ECMAScript 词法环境全解析
前端
青青家的小灰灰3 小时前
React 架构进阶:自定义 Hooks 的高级设计模式与最佳实践
前端·react.js·前端框架
Angelial3 小时前
Vite 性能瓶颈排查标准流程
前端
不要秃头啊3 小时前
别再谈提效了:AI 时代的开发范式本质变了
前端·后端·程序员
青青家的小灰灰3 小时前
深入理解事件循环:异步编程的基石
前端·javascript·面试
用泥种荷花3 小时前
【LangChain.js学习】 向量数据库(内存/持久化)
前端