简体   繁体   English

使用 .attr() 添加数据属性时出现“TypeError: undefined is not an object”

[英]"TypeError: undefined is not an object" when using .attr() to add data attribute

I'm creating a bar graph and I need to show a tooltip when hovering over each bar.我正在创建一个条形图,我需要在将鼠标悬停在每个条形上时显示一个工具提示。 The tooltip must include a data attribute with the bar's date information.工具提示必须包含带有条形日期信息的数据属性。 Using .attr("data-date", d => d[0]) I added the attribute to the bars, and yet it shows an error when used in the tooltip.使用 .attr("data-date", d => d[0]) 我将该属性添加到条形图中,但在工具提示中使用时显示错误。 (The tooltip works just fine if I remove line 53). (如果我删除第 53 行,工具提示就可以正常工作)。

const w = 1000;
const h = 550;
const padding = 50;
const barPadding = 0.5;
 d3.json(
  "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json",
  json => {
    const minDate = d3.min(json.data, d => d[0]);
    const maxDate = d3.max(json.data, d => d[0]);
    const max = d3.max(json.data, d => d[1]);

    const xScale = d3
      .scaleTime()
      .domain([new Date(minDate), new Date(maxDate)])
      .range([padding, w - padding]);

    const yScale = d3
      .scaleLinear()
      .domain([0, max])
      .range([h - padding, padding]);

    const tooltip = d3
      .select("#container")
      .append("div")
      .attr("id", "tooltip")
      .style("width", padding);

    const svg = d3
      .select("#container")
      .append("svg")
      .attr("width", w)
      .attr("height", h);

    svg
      .selectAll("rect")
      .data(json.data)
      .enter()
      .append("rect")
      .attr("x", (d, i) => xScale(new Date(d[0])))
      .attr("y", d => yScale(d[1]))
      .attr("width", w / json.data.length - barPadding)
      .attr("height", d => h - yScale(d[1]) - padding)
      .attr("class", "bar")
      .attr("data-date", d => d[0])
      .attr("data-gdp", d => d[1])
      .on("mouseover", (d, i) => {
        console.log(d[0]);
        tooltip
          .style("visibility", "visible")
          .style("top", `${yScale(d[1])}px`)
          .style("left", `${xScale(new Date(d[0])) - padding}px`)
          .attr("data-date", d => d[0])
          .html(`${d[0]} <br/> $${d[1]} Billion`);
      })
      .on("mouseout", () => tooltip.style("visibility", "hidden"));

    const xAxis = d3.axisBottom(xScale);
    const yAxis = d3.axisLeft(yScale);

    svg
      .append("g")
      .attr("transform", `translate(0, ${h - padding})`)
      .attr("id", "x-axis")
      .call(xAxis);

    svg
      .append("g")
      .attr("transform", `translate(${padding}, 0)`)
      .attr("id", "y-axis")
      .call(yAxis);
  }
);

Any help is appreciated.任何帮助表示赞赏。 Fiddle: http://jsfiddle.net/s1tpyuoc/小提琴: http : //jsfiddle.net/s1tpyuoc/

Let's simplify your code and see what you have:让我们简化你的代码,看看你有什么:

selection.on("mouseover", (d, i) => {
    tooltip.attr("data-date", d => d[0]);
})

You may think that this sets the first element of d as the "data-date" property of tooltip .您可能认为这将d的第一个元素设置为tooltip"data-date"属性。 But it doesn't: that second d in the callback of the attr method is not the same d of the selection:但事实并非如此:这第二d的回调attr方法是不一样的d的选择:

selection.on("mouseover", (d, i) => {
    //this datum... -------^
    tooltip.attr("data-date", d => d[0]);
    //...is not the same of this---^
})

And, since there is no data bound to tooltip , that inner d is undefined .而且,由于没有绑定到tooltip数据,因此内部dundefined

The solution here is simply removing that line or, for whatever reason you want to set that attribute, doing:这里的解决方案是简单地删除该行,或者无论出于何种原因要设置该属性,请执行以下操作:

tooltip.attr("data-date", d[0])

Here is the updated JSFiddle: http://jsfiddle.net/vxq9gcwr/这是更新的 JSFiddle: http : //jsfiddle.net/vxq9gcwr/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM