关键词:深度图、虚拟货币、HTML5 Canvas、订单数据、成交量、买卖盘可视、加密货币、交易决策、前端开发、实时行情
一、深度图是什么?30 秒讲透买卖盘逻辑
深度图(Depth Chart)是虚拟货币交易所最常用的一种买卖力量对比工具。横轴罗列价格,纵轴为对应价格的累计成交量。左侧绿色曲线代表“买方力量”,右侧红色曲线代表“卖方力量”。两条曲线之间的距离揭示市场流动性:距离越远,买卖价差越大;距离越近,成交就越紧密。
一句话总结:深度图就是用最直观的方式告诉你,当下想要吃掉多少货、价格会被推到什么位置。
二、项目目标:不靠第三方,3 步完成可运行深度图
- 零基础搞懂深度图含义与阅读技巧
- 用 HTML5 Canvas 原生 API 绘制、交互、调试
- 给出完整源代码,你可以直接嵌入页面或结合 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}
]
}数据规律:
- 卖单价格低 → 高,买单价格高 → 低
- “amount” 为本档挂单量,“total” 为从下往上/从上往下累加,后续绘图就靠它
四、核心算法:如何计算累计成交量
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. 布局设计
- 画布总宽
canvas.width = 600 - 画布总高
canvas.height = 300 - 预留刻度区:
margin = 40px - Y 轴方向需要倒置(价格越高、点越往下),用公式
y = canvas.height - margin - normalizedTotal
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 种实用交互技巧
- 鼠标悬停时横向标线联动,实时展示“把 X BTC 推到 9000 USDT”需要吃掉的深度。
- 滚轮缩放价格区间,观察微观流动性。
- 颜色渐变启停,同步提示进场/出场信号(绿色变大红可能预示杀跌)。
示例代码(鼠标坐标 → 对应价格):
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 频道 depth 或 diffDepth 每 100 ms 推送增量,只修改差异部分,再按“增量更新累计量”算法即可,整体 CPU 占用 <5%。
八、结语与下一步
通过本文,你已掌握:
- 深度图的真实含义与交易应用
- HTML5 Canvas 原生绘制思路及核心算法
- 完整代码实践,既可插入静态报告,也可接入实时行情系统
将这段逻辑再封装成可复用 ES Module,就能在数分钟内把深度图嵌入产品页、行情屏、量化 dashboards,助用户以最低学习成本做出最佳交易决策。