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

D3.js从v3迁移至v7后鼠标点击完成矩形绘制功能失效问题求助

问题排查

你在D3.js v3到v7迁移中出现的绘制无响应问题,由以下几个版本适配错误导致:

  • 事件参数适配错误:D3 v6开始所有事件回调的第一个入参为事件对象,原代码中dragRect拖拽回调未接收该参数,直接调用全局event触发undefined报错,阻塞整个绘制逻辑
  • 事件重复绑定:每次触发Rectangle()构造函数都会给svg重复绑定鼠标事件,多次调用后逻辑完全混乱
  • 拖拽坐标计算错误:原拖拽逻辑直接累加鼠标绝对坐标,会导致矩形瞬间偏移出可视区,看不到绘制结果
  • 缺少明显的矩形样式:默认填充为黑色的矩形如果和页面背景色一致会无法观测到绘制结果

修复后可运行代码

// 绑定绘制按钮点击事件,先移除已有事件避免重复绑定
d3.select('#rectangle').off('click').on('click', (event) => {
  event.preventDefault();
  new Rectangle();
});

const w = 600, h = 500;
const svg = d3.select('body')
  .append('svg')
  .attr("width", w)
  .attr("height", h)
  // 阻止右键默认菜单弹出
  .on('contextmenu', (event) => event.preventDefault());

function Rectangle() {
  const self = this;
  let isDown = false;
  let isDrag = false;
  let m1, m2;

  // 绑定事件前先移除旧的同名事件,避免重复绑定
  svg.off('mousedown').off('mousemove')
    .on('mousedown', (event) => {
      m1 = d3.pointer(event);
      if (!isDown && !isDrag) {
        self.rectData = [ { x: m1[0], y: m1[1] }, { x: m1[0], y: m1[1] } ];
        // 给矩形添加可见样式
        self.rectangleElement = d3.select('svg').append('rect')
          .attr('class', 'rectangle')
          .style('fill', 'none')
          .style('stroke', '#f43f5e')
          .style('stroke-width', '2px')
          .call(dragR);
        updateRect();
        isDrag = false;
      } else { 
        isDrag = true;
      }
      isDown = !isDown;     
    })
    .on('mousemove', (event) => {
      m2 = d3.pointer(event);
      if(isDown && !isDrag) { 
        self.rectData[1] = { x: m2[0], y: m2[1] };
        updateRect();
      } 
    });  
  
  function updateRect() {  
    const rect = self.rectangleElement;
    const x1 = self.rectData[1].x - self.rectData[0].x > 0 ? self.rectData[0].x :  self.rectData[1].x;
    const y1 = self.rectData[1].y - self.rectData[0].y > 0 ? self.rectData[0].y :  self.rectData[1].y;
    rect.attr("x", x1)
      .attr("y", y1)
      .attr("width", Math.abs(self.rectData[1].x - self.rectData[0].x))
      .attr("height", Math.abs(self.rectData[1].y - self.rectData[0].y));
  }

  const dragR = d3.drag().on('drag', dragRect);

  function dragRect(event) {
    // 使用d3.drag内置的偏移量计算坐标
    const dx = event.dx;
    const dy = event.dy;
    self.rectData.forEach(point => {
      point.x += dx;
      point.y += dy;
    })
    self.rectangleElement.style('cursor', 'move');
    updateRect();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:06:05