You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3.js蜡烛图鼠标悬停获取单根K线的开/高/低/收盘价

在D3.js蜡烛图中实现鼠标悬停获取K线数据

我来帮你搞定这个问题!之前你尝试用group元素没成功,大概率是在数据绑定或者事件监听的环节没处理到位。下面是一套完整的解决方案,一步步帮你实现鼠标悬停时获取单根K线的开盘、最高、最低、收盘价:

核心思路

把每根蜡烛的所有组件(影线、实体)包裹在一个<g>元素里,将对应的K线数据直接绑定到这个group上。这样鼠标悬停在蜡烛的任何区域时,都能轻松拿到该K线的完整数据。

完整代码示例

$(document).ready(function () {
  // 示例K线数据,替换成你自己的数据源
  const candlestickData = [
    { open: 100, high: 105, low: 98, close: 102, date: '2024-01-01' },
    { open: 102, high: 106, low: 99, close: 104, date: '2024-01-02' },
    { open: 104, high: 107, low: 101, close: 103, date: '2024-01-03' },
    // 更多K线数据...
  ];

  // SVG容器的基础设置(根据你的实际页面调整尺寸)
  const svgWidth = 800;
  const svgHeight = 400;
  const margin = { top: 20, right: 20, bottom: 30, left: 50 };
  const barWidth = 12; // 蜡烛实体的宽度

  // 创建SVG容器
  const svg = d3.select("body")
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .append("g")
    .attr("transform", `translate(${margin.left}, ${margin.top})`);

  // 定义比例尺(根据你的数据范围调整定义域)
  const xScale = d3.scaleBand()
    .domain(candlestickData.map(d => d.date))
    .range([0, svgWidth - margin.left - margin.right])
    .padding(0.3);

  const yScale = d3.scaleLinear()
    .domain([d3.min(candlestickData, d => d.low) - 2, d3.max(candlestickData, d => d.high) + 2])
    .range([svgHeight - margin.top - margin.bottom, 0]);

  // 为每根K线创建group元素并绑定数据
  const candleGroups = svg.selectAll(".candle-group")
    .data(candlestickData)
    .enter()
    .append("g")
    .attr("class", "candle-group")
    // 定位group到对应日期的x坐标中心
    .attr("transform", d => `translate(${xScale(d.date) + xScale.bandwidth()/2}, 0)`);

  // 绘制蜡烛影线(连接最高价和最低价)
  candleGroups.append("line")
    .attr("class", "candle-wick")
    .attr("x1", 0)
    .attr("x2", 0)
    .attr("y1", d => yScale(d.high))
    .attr("y2", d => yScale(d.low))
    .attr("stroke", "#333")
    .attr("stroke-width", 1);

  // 绘制蜡烛实体(开盘价到收盘价的矩形)
  candleGroups.append("rect")
    .attr("class", "candle-body")
    .attr("x", -barWidth/2)
    // 矩形的y坐标取开盘和收盘中的较大值
    .attr("y", d => yScale(Math.max(d.open, d.close)))
    // 矩形高度是开盘和收盘的y坐标差的绝对值
    .attr("height", d => Math.abs(yScale(d.open) - yScale(d.close)))
    .attr("width", barWidth)
    // 上涨绿色,下跌红色
    .attr("fill", d => d.close >= d.open ? "#2ecc71" : "#e74c3c");

  // 添加鼠标悬停事件
  candleGroups
    .on("mouseover", function(event, d) {
      // 这里的d就是当前悬停K线的完整数据,直接取用即可
      console.log("当前K线数据:", {
        开盘价: d.open,
        最高价: d.high,
        最低价: d.low,
        收盘价: d.close,
        日期: d.date
      });

      // 如果你需要显示tooltip,先在HTML里加一个tooltip元素
      d3.select("#tooltip")
        .style("display", "block")
        .style("left", `${event.pageX + 10}px`)
        .style("top", `${event.pageY - 10}px`)
        .html(`
          <p><strong>日期:</strong> ${d.date}</p>
          <p><strong>开盘:</strong> ${d.open}</p>
          <p><strong>最高:</strong> ${d.high}</p>
          <p><strong>最低:</strong> ${d.low}</p>
          <p><strong>收盘:</strong> ${d.close}</p>
        `);
    })
    .on("mouseout", function() {
      // 鼠标移出时隐藏tooltip
      d3.select("#tooltip").style("display", "none");
    });
});

关键注意事项

  • 数据绑定正确性:通过.data(candlestickData)把数组数据绑定到每个group上,确保每个group对应一根K线的完整数据。
  • Group定位:用transform属性把group定位到对应日期的x坐标中心,这样蜡烛的影线和实体都能居中显示。
  • Tooltip准备:需要在HTML里提前添加tooltip元素,样式设置为绝对定位:
<div id="tooltip" style="position: absolute; display: none; background: #fff; padding: 8px; border: 1px solid #ddd; border-radius: 4px; pointer-events: none; font-size: 14px;"></div>
  • 比例尺适配:根据你自己的实际数据调整xScale和yScale的定义域,确保蜡烛能正确显示在SVG容器内。

如果你之前添加group没成功,大概率是没有正确处理enter()环节,或者没有给group设置正确的transform定位。按照上面的代码来,应该就能顺利实现需求啦!

内容的提问来源于stack exchange,提问作者S.Diksha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:39:06