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

D3.js气泡图响应式尺寸缩小后右侧数据无法渲染问题

解决D3.js响应式气泡图小窗口下右侧元素不渲染的问题

问题根源

你的气泡图在小窗口下右侧元素消失,主要由三个问题导致:

  • X轴比例尺的range用了固定比例dimensions.width * 0.85,未结合margin和气泡半径预留空间,导致x值接近100的气泡超出可视区域
  • SVG自身和坐标轴的transform偏移逻辑混乱,叠加后进一步压缩了右侧绘图空间
  • 初始宽高为固定值,未结合容器动态尺寸更新

解决方案

1. 修正X轴比例尺的范围计算

去掉固定的0.85比例,基于容器宽度减去左右margin后的可用空间设置range,同时给右侧预留气泡半径的空间,避免边缘气泡被截断:

const margin = { top: 10, right: 30, bottom: 30, left: 40 };
const usableWidth = dimensions.width - margin.left - margin.right;

const xscale = d3
  .scaleLinear()
  .domain([0, 100])
  // 10为预估的最大气泡半径,可根据实际数据调整
  .range([0, usableWidth - 10]);

2. 统一绘图区域的偏移逻辑

不要给SVG元素加transform,而是创建一个主绘图组,用它统一处理margin偏移,后续所有图表元素(坐标轴、气泡)都添加到这个组中:

// 清空SVG后创建主绘图组
const g = svg.append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`);

// X轴添加到主组中,基于主组的y偏移定位
g.append("g")
  .call(x_axis)
  .attr("transform", `translate(0, ${height})`)
  .style("stroke-width", 0.3)
  .call(g => g.select(".domain").remove());

3. 动态计算图表高度

将固定高度改为结合容器尺寸的动态值,保证响应式适配:

// 优先使用容器高度,否则 fallback 到固定值
const height = dimensions.height 
  ? (dimensions.height - margin.top - margin.bottom) 
  : 330;

4. 修正SVG尺寸设置

确保SVG宽度为容器完整宽度,高度为动态计算后的总高度:

svg
  .attr("width", dimensions.width)
  .attr("height", height + margin.top + margin.bottom);

修改后的核心代码片段

useEffect(() => {
  const svg = d3.select(mySVGRef.current);
  if (!dimensions) return;

  svg.html(null);

  const margin = { top: 10, right: 30, bottom: 30, left: 40 };
  const usableWidth = dimensions.width - margin.left - margin.right;
  const height = dimensions.height 
    ? (dimensions.height - margin.top - margin.bottom) 
    : 330;

  // 设置SVG基础尺寸
  svg
    .attr("width", dimensions.width)
    .attr("height", height + margin.top + margin.bottom);

  // 创建统一的绘图组
  const g = svg.append("g")
    .attr("transform", `translate(${margin.left}, ${margin.top})`);

  // 修正后的X比例尺
  const xscale = d3
    .scaleLinear()
    .domain([0, 100])
    .range([0, usableWidth - 10]);

  const x_axis = d3
    .axisBottom(xscale)
    .tickValues(d3.range(0, 101, 25));

  // 添加X轴
  g.append("g")
    .call(x_axis)
    .attr("transform", `translate(0, ${height})`)
    .style("stroke-width", 0.3)
    .call(g => g.select(".domain").remove());

  g.selectAll(".tick text").attr("fill", "#777");

  // 气泡绘制示例(根据你的实际数据调整)
  g.selectAll("circle")
    .data(data)
    .enter()
    .append("circle")
    .attr("cx", d => xscale(d.x)) // 假设数据中有x字段对应0-100的值
    .attr("cy", d => height / 2) // 示例Y坐标,替换为你的Y比例尺计算逻辑
    .attr("r", d => d.radius) // 示例半径,替换为你的实际半径计算
    .attr("fill", "#69b3a2");

}, [data, dimensions]);

内容的提问来源于stack exchange,提问作者ta7foun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:02:09