HTML5 Canvas 虚拟货币深度图实战:从数据源到可交互图表一步到位

·

关键词:深度图、虚拟货币、HTML5 Canvas、订单数据、成交量、买卖盘可视、加密货币、交易决策、前端开发、实时行情

一、深度图是什么?30 秒讲透买卖盘逻辑

深度图(Depth Chart)是虚拟货币交易所最常用的一种买卖力量对比工具。横轴罗列价格,纵轴为对应价格的累计成交量。左侧绿色曲线代表“买方力量”,右侧红色曲线代表“卖方力量”。两条曲线之间的距离揭示市场流动性:距离越远,买卖价差越大;距离越近,成交就越紧密。
一句话总结:深度图就是用最直观的方式告诉你,当下想要吃掉多少货、价格会被推到什么位置

👉 想亲手试一下深度图如何实时捕捉行情波动?

二、项目目标:不靠第三方,3 步完成可运行深度图

  1. 零基础搞懂深度图含义与阅读技巧
  2. 用 HTML5 Canvas 原生 API 绘制、交互、调试
  3. 给出完整源代码,你可以直接嵌入页面或结合 WebSocket 刷新实时数据

三、准备工作:准备 20 条核心数据

深度图并不需要全量订单,以 BTC/USDT 为例,我们取 买单前 10 档 + 卖单前 10 档 即可形成清晰轮廓。下面给出 JSON 结构,后续所有绘图逻辑都围绕它展开:

{
  "sell":[
    {"price":9000,"amount":8176},{"price":8999.84,"amount":10245},{"price":8999.68,"amount":19147},
    {"price":8999.52,"amount":4150},{"price":8999.36,"amount":10420},{"price":8999.2,"amount":16053},
    {"price":8999.04,"amount":8480},{"price":8998.88,"amount":12751},{"price":8998.72,"amount":14187},
    {"price":8998.56,"amount":7916}
  ],
  "buy":[
    {"price":8749,"amount":8379},{"price":8748.74,"amount":18582},{"price":8748.48,"amount":9173},
    {"price":8748.22,"amount":13327},{"price":8747.96,"amount":1990},{"price":8747.7,"amount":3414},
    {"price":8747.44,"amount":12062},{"price":8747.18,"amount":19389},{"price":8746.92,"amount":8999},
    {"price":8746.66,"amount":8675}
  ]
}

数据规律:

四、核心算法:如何计算累计成交量

Canvas 绘图并非直接绘制零散点,而是连线成面。先为每个价格计算其“之上”或“之下”的总堆单量。

买单累计逻辑

let cumBuy = 0;
data.buy.forEach((item, idx) => {
  cumBuy += item.amount;
  item.total = cumBuy;   // price=x 时,累计买单量
});

卖单累计逻辑

let cumSell = 0;
// 注意:倒序遍历,求得“<= 此价格”总挂单
for (let i = data.sell.length - 1; i >= 0; i--) {
  cumSell += data.sell[i].amount;
  data.sell[i].total = cumSell;
}

累加完成后,每条记录就具备了绘图所需的 (price, total) 坐标。

五、Canvas 绘图拆解:一条折线如何演化成深度曲面

HTML5 Canvas 坐标系起点在左上角,向右为 X 轴正,向下为 Y 轴正。为了画出买入/卖出两条“墙”,我们把价格映射到 X 轴,累计量映射到 Y 轴,最后用贝塞尔或 lineTo 连接即可。

1. 布局设计

2. 创建路径

// 买单路径(绿色)
ctx.beginPath();
ctx.moveTo(margin, zeroY);
data.buy.forEach((p) => {
  const x = xScale(p.price);
  const y = yScale(p.total);
  ctx.lineTo(x, y);
});
ctx.lineTo(centerX, zeroY); // 闭合到底
ctx.fillStyle = 'rgba(0,200,100,0.3)';
ctx.fill();

// 卖单路径(红色)
ctx.beginPath();
ctx.moveTo(centerX, zeroY);
data.sell.forEach((p) => {
  const x = xScale(p.price);
  const y = yScale(p.total);
  ctx.lineTo(x, y);
});
ctx.lineTo(canvas.width - margin, zeroY);
ctx.fillStyle = 'rgba(200,50,50,0.3)';
ctx.fill();

👉 点这里查看完整可交互深度图示例代码,复制即用

3. 动态刷新

使用 AJAX 轮询或 WebSocket 订阅频道,每次新数据抵达时清空画布 → 重新累积总量 → 重绘路径,整个过程 60 FPS 也不过几毫秒,对前端性能几乎零负担。

六、让深度图会说话:3 种实用交互技巧

  1. 鼠标悬停时横向标线联动,实时展示“把 X BTC 推到 9000 USDT”需要吃掉的深度。
  2. 滚轮缩放价格区间,观察微观流动性。
  3. 颜色渐变启停,同步提示进场/出场信号(绿色变大红可能预示杀跌)。

示例代码(鼠标坐标 → 对应价格):

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const price = x.invert(xScale); // 用逆函数拿到 price
  drawCrossHair(price);
});

七、常见疑问(FAQ)

Q1:为什么只用前 20 档,而不是全量订单?
A:深度图旨在“一眼看穿”挂单薄厚。过多尾部订单会让曲线太平,失去洞察价值;数字货币交易所 API 也普遍限量返回前 N 档,兼顾性能与易读。

Q2:如何兼容移动端小屏?
A:使用 devicePixelRatio 调整 Canvas 物理像素,避免锯齿;同时放大触摸点热区,例如把 1 px 灵敏区域扩到 8 px,体验更友好。

Q3:可以添加订单薄差异高亮吗?
A:可以把前后两次快照做 diff,若某档量增加 >20%,将该区间改用高饱和度颜色重绘,迅速捕捉“鲸鱼”入场。

Q4:多币种怎么办?需改坐标吗?
A:横轴价格自动由 min(price) * 0.99 ~ max(price) * 1.01 线性映射即可;纵轴总量用对数尺,避免 BTC、ETH 数量级差异造成的显示断层。

Q5:是否一定要 Canvas?SVG 行不行?
A:SVG 优势在 DOM 级交互、CSS 样式;Canvas 优势在超大数据量绘制、高帧动画。考虑到订单累积动辄上千点,Canvas 仍是首选;如只需静态展示,SVG 亦可。

Q6:如何接入实时数据?
A:交易所 WebSocket 频道 depthdiffDepth 每 100 ms 推送增量,只修改差异部分,再按“增量更新累计量”算法即可,整体 CPU 占用 <5%。

八、结语与下一步

通过本文,你已掌握:

将这段逻辑再封装成可复用 ES Module,就能在数分钟内把深度图嵌入产品页、行情屏、量化 dashboards,助用户以最低学习成本做出最佳交易决策。