You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

D3元素提示未定义排查:WebSocket接收JSON绘制散点图代码求助

解决D3未定义问题并完善实时散点图绘制逻辑

一、搞定D3未定义的报错

D3提示未定义,基本都是库没加载对,按这几步排查:

  • 先确认你引入了D3库:所有用到D3的代码,必须在D3加载完成后再执行。你需要在HTML里添加D3的脚本标签,放在<head>或者你的WebSocket脚本之前——可以从D3官方获取CDN地址,或者下载本地文件,格式大概是这样:
    <script src="替换为D3的CDN地址/本地文件路径"></script>
    
  • 检查脚本加载顺序:别把你的自定义脚本(比如处理绘图的graphData函数)放在D3脚本前面,不然浏览器执行到D3代码时还没加载库,肯定报错。
  • 检查脚本的type属性:你提到第二个脚本标签写了type="te...",这大概率是type="text/javascript"的拼写错误,错误的type会让浏览器跳过执行这个脚本,自然找不到D3。要么把type写对,要么现代浏览器可以直接省略这个属性。

二、完善实时散点图的绘制逻辑

假设你从WebSocket收到的value是一个对象数组,每个对象包含xy坐标(比如[{x: 12, y: 34}, {x: 23, y: 45}, ...]),下面是完整的graphData函数实现,支持实时更新数据(毕竟WebSocket是推数据,得能动态刷新图表):

function graphData(data) {
  // 1. 设置画布的边距和尺寸
  const margin = { top: 20, right: 30, bottom: 30, left: 40 };
  const width = 600 - margin.left - margin.right;
  const height = 400 - margin.top - margin.bottom;

  // 2. 初始化SVG容器(如果还没创建的话)
  let svg = d3.select("#visualisation").select("svg");
  if (svg.empty()) {
    // 创建SVG和主绘图区域
    svg = d3.select("#visualisation")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", `translate(${margin.left}, ${margin.top})`);

    // 初始化x、y轴的比例尺
    const xScale = d3.scaleLinear().range([0, width]);
    const yScale = d3.scaleLinear().range([height, 0]);

    // 添加x轴
    svg.append("g")
      .attr("class", "x-axis")
      .attr("transform", `translate(0, ${height})`)
      .call(d3.axisBottom(xScale));

    // 添加y轴
    svg.append("g")
      .attr("class", "y-axis")
      .call(d3.axisLeft(yScale));

    // 把比例尺存在SVG的data里,方便后续更新用
    svg.data([{ xScale, yScale }]);
  }

  // 3. 获取之前保存的比例尺
  const scales = svg.data()[0];
  const xScale = scales.xScale;
  const yScale = scales.yScale;

  // 4. 根据新数据更新比例尺的定义域
  xScale.domain([0, d3.max(data, d => d.x)]);
  yScale.domain([0, d3.max(data, d => d.y)]);

  // 5. 更新坐标轴
  svg.select(".x-axis").call(d3.axisBottom(xScale));
  svg.select(".y-axis").call(d3.axisLeft(yScale));

  // 6. 绑定数据,绘制散点(用enter-update-exit模式处理动态数据)
  const points = svg.selectAll(".dot")
    .data(data);

  // 移除旧的、不需要的点
  points.exit().remove();

  // 添加新的点,同时更新已有点的位置
  points.enter()
    .append("circle")
    .attr("class", "dot")
    .attr("r", 5) // 点的半径
    .attr("fill", "#2c3e50") // 点的颜色
    .merge(points)
    .attr("cx", d => xScale(d.x))
    .attr("cy", d => yScale(d.y));
}

几点注意事项:

  • 如果你的value数据结构不一样(比如坐标属性不是xy),只要把代码里的d.xd.y改成你实际的属性名就行。
  • 这个函数支持每次收到新数据后自动更新图表,不会重复创建SVG和坐标轴,适合实时数据流场景。
  • 你可以根据需求调整画布大小、点的尺寸、颜色,甚至添加 tooltip 之类的交互效果。

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

火山引擎 最新活动