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

d3 v5+ 可复用图表模式下如何实现拖拽事件分发?

问题原因及修复方案

1. 选择集未合并导致拖拽事件未绑定到元素

你当前仅将拖拽事件绑定到了discs这个更新选择集上,新通过enter阶段创建的circle元素没有被包含在该选择集中,因此拖拽事件根本没有生效。需要在enter操作后合并enter和更新选择集,再绑定拖拽事件。

2. 拖拽事件参数取值错误

如果使用的是D3 v6及以上版本,全局d3.event已被废弃,拖拽事件回调的第一个参数即为事件对象,第二个才是绑定的数据。你之前的写法拿不到正确的坐标值,同时需要将事件对象通过dispatcher传递到外部回调。


对应修改代码

图表内部拖拽逻辑修改

// 假设此处的discs是你绑定数据后的更新选择集
discs.exit().remove();

const discsEnter = discs.enter()
    .append('circle')
    .attr('class', 'Discs')
    .attr('cx', 50)
    .attr('cy', 50)
    .attr('r', 20)
    .attr('stroke', 'black')
    .attr('fill', '#69a3b2');

// 合并enter与更新选择集
const discsMerge = discsEnter.merge(discs);

let dragHandler = d3.drag()
    // 第一个参数为事件对象,第二个为绑定的数据d
    .on('drag', function(event, d) {
        // 将事件对象传递到外部回调
        dispatcher.call('customDrag', this, event, d);
    });

// 给合并后的所有元素绑定拖拽事件
discsMerge.call(dragHandler);

外部调用逻辑修改

let position = [50]
let myChart = d3.reusable.chart()
   .on('customDrag', function(event, d){
        d3.select(this).classed("dragging", true)
            // 直接从回调的event参数取坐标
            .attr('cx', event.x)
            .attr('cy', event.y);
});

d3.select("#chart")
    .datum(position) 
    .call(myChart);

如果使用的是D3 v5及更早版本,只需保留选择集合并的修改,事件回调仍可使用d3.event.x、d3.event.y取值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:30:02