使用D3.js+TypeScript实现矩形悬停显示数值遇类型错误
我用TypeScript结合D3.js开发数据可视化图表,黑色矩形的高度由generateData生成的正数决定。希望鼠标悬停在矩形上时显示对应的数值,但出现了TypeScript类型错误。
错误信息
没有匹配的重载调用。
重载1(共2个):'(selector: string): Selection<BaseType, unknown, HTMLElement, any>',给出以下错误:
参数类型“ParentNode | null”无法赋值给参数类型“string”。类型“null”无法赋值给参数类型“string”。
重载2(共2个):'(node: BaseType): Selection<BaseType, unknown, null, undefined>',给出以下错误:
参数类型“ParentNode | null”无法赋值给参数类型“BaseType”。类型“ParentNode”无法赋值给类型“BaseType”。类型“ParentNode”缺少类型“Document”的以下属性:URL、alinkColor、all、anchors等191个属性。ts(2769)
当前代码
const data = generateData(50); const margin = { top: 10, right: 30, bottom: 30, left: 40 }, width = 800 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; const svg = d3 .select(".visualization") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); const rects = svg.selectAll("rect").data(data).enter().append("rect"); rects .attr("x", (_, i) => i * (width / data.length)) .attr("y", (d) => height - d) .attr("width", () => width / data.length - 1) .attr("height", (d) => d) .on("mouseover", function (d, i) { d3.select(this.parentNode).append("text").text(d); }); export {};
修复方案
错误根源
this.parentNode的类型是ParentNode | null,而D3的select()方法仅接受字符串选择器或符合BaseType的节点,TypeScript严格类型检查下两者不兼容。
具体修复步骤
类型断言兼容节点类型
给this.parentNode添加类型断言,明确告诉TypeScript它是有效的SVG元素:d3.select(this.parentNode as SVGElement)修正D3事件参数顺序(D3 v6+)
D3 v6及之后的事件处理函数参数顺序为(event, d),而非旧版的(d, i),参数顺序错误会导致数据获取异常,修正后:.on("mouseover", function (event, d) { // 后续逻辑 })完善提示文本定位与避免重复创建
新增文本时添加定位逻辑,同时在鼠标移出时移除提示,避免重复元素堆积:rects .attr("x", (_, i) => i * (width / data.length)) .attr("y", (d) => height - d) .attr("width", () => width / data.length - 1) .attr("height", (d) => d) .on("mouseover", function (event, d) { const parent = d3.select(this.parentNode as SVGElement); // 移除已存在的提示文本 parent.selectAll(".tooltip-text").remove(); // 添加新的提示文本并定位 parent.append("text") .attr("class", "tooltip-text") .attr("x", +d3.select(this).attr("x")!) .attr("y", +d3.select(this).attr("y")! - 5) // 文本置于矩形上方 .attr("font-size", "12px") .text(d.toString()); }) .on("mouseout", function () { // 鼠标移出时删除提示 d3.select(this.parentNode as SVGElement).selectAll(".tooltip-text").remove(); });
内容的提问来源于stack exchange,提问作者kluzix

