D3.js折线图鼠标悬停数据点返回undefined问题求解
问题原因
你遇到的是D3 v6+版本的事件回调参数变更导致的取值异常:
- D3 v5及更早版本中,事件监听回调的第一个参数为绑定的数据对象,第二个参数为索引
- D3 v6及之后版本,事件监听回调的第一个参数改为事件对象,绑定的数据对象调整为第二个参数
你当前代码中拿到的d实际是浏览器事件对象,自然不存在d[0]/d.Wavelength属性,所以取值为undefined。
修复方案
1. 修正事件绑定的参数顺序
将所有绑定的鼠标事件回调都调整参数顺序,第一个参数接收事件,第二个参数接收绑定数据:
svg.selectAll('circle_samp_1') .data(data_in_range) .enter() .append('circle') .attr('cx', (d) => xScale(d[0])) .attr('cy', (d) => yScale(d[1])) .attr('r', 7) .attr('fill', 'rgba(0,0,0,0.1)') .attr('stroke', 'rgba(0,0,0,0.9)') .attr('stroke-width', 1) .attr('class', 'points') .style('pointer-events', 'all') // 调整参数,第一个为event,第二个为数据d .on("mouseover",function (event, d){ return m_over(d) }) .on("mousemove", function (event, d) { return m_move(d) }) .on("mouseout", function (event, d) { return m_out(d) });
修改后m_over方法中的d[0]、d[1]就可以正常取到对应值。
2. 修正bisect相关逻辑的错误
你参考的bisect示例代码存在逻辑错误:xScale(data[i - 1])返回的是像素坐标数值,不是原始数据对象,无法获取Wavelength属性,需要调整为直接取原始数据:
function mousemove(event) { var x0 = xScale.invert(d3.pointer(event, this)[0]), i = d3.bisect(d => d[0], x0, 1), // 这里指定bisect的取值键为数据第一个元素 d0 = data[i - 1], // 直接取原始数据,不要套xScale d1 = data[i], d = x0 - d0[0] > d1[0] - x0 ? d1 : d0; // 后续用d来填充tooltip内容即可 }
如果调整后仍存在问题,可以打印data_in_range确认数据结构是否符合预期,确保每条数据都是数组格式、下标0对应Wavelength、下标1对应吸光度值。
内容的提问来源于stack exchange,提问作者Bigboss01
相关产品推荐
相关产品推荐

