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
相关产品推荐
相关产品推荐

