更新d3散点图,新数据点位置不正确

时间:2017-11-29 20:54:50

标签: javascript d3.js plot scatter-plot

花了很多时间,仍然不确定是什么问题。

我的情节应该根据用户选择的一堆参数进行更新。当绘图需要添加新数据点时,新点将无法在绘图中正确显示。

查看新图:

Check out the new plot here

使用这些参数,所有圆圈都应该在一条线上。虽然原始的“线”位于正确的位置,但新的“线”与网格不匹配。

这是制作新情节的功能。这很好用,所有数据点都应该是它们的位置。

export const newPlot = (Params) => {
  d3.selectAll("svg").remove();

  let margin = {top: 50, right: 20, bottom: 30, left: 40},
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  let x = d3.scaleLinear().range([0, width]);
  let y = d3.scaleLinear().range([height, 0]);


  let svg = d3.select('.plot').append("svg")
      .attr('class', 'svgPlot')
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform","translate(" + margin.left + "," + margin.top + ")");


    d3.json(`../assets/data/${Params.type}${Params.Year}.json`, (error, data) => {
      if (error) throw error;

      const refinedData = parametrize(data, Params);
      refinedData.forEach((d) => {
        d[Params.xSelect] = Number(d[Params.xSelect]);
        d[Params.ySelect] = Number(d[Params.ySelect]);
      });

      let min = d3.min(refinedData,(d) => d[Params.xSelect]);
      x.domain([(min - 2 <= 0 ? 0 : min - 2),
                d3.max(refinedData,(d) => d[Params.xSelect])]);
      y.domain([0, d3.max(refinedData,(d) => d[Params.ySelect])]);


      svg.selectAll("circles")
        .data(refinedData)
      .enter().append("circle")
        .attr('id', (d) => `${d.Player}`)
        .attr("r", 5)
        .attr("cx", (d) =>  x((d[Params.xSelect])) )
        .attr("cy", (d) => y((d[Params.ySelect])) );



      svg.append("g")
         .attr("class", "x-axis")
         .attr("transform", "translate(0," + height + ")")
         .call(d3.axisBottom(x));


     svg.append("g")
         .attr("class", "y-axis")
         .call(d3.axisLeft(y));


      svg.append('text')
      .attr("class", "label")
      .attr('id', 'xlabel')
      .attr("transform","translate(" + (width - 20) + " ," + (height-5) + ")")
      .style("fill", "white")
      .style("text-anchor", "middle")
      .text(`${Params.xSelect}`);

      svg.append('text')
        .attr("class", "label")
        .attr('id', 'ylabel')
        .attr("transform", "rotate(-90)")
        .attr("y", 1)
        .attr("x", (height/2 - 250))
        .attr("dy", "1em")
        .style("font-family", "sans-serif")
        .style("fill", "white")
        .style("text-anchor", "middle")
        .text(`${Params.ySelect}`);
      });

};

这是更新功能。添加的圆圈位于正确的位置,并且全部偏移相同的数量。

export const rePlot = (Params) => {

  let margin = {top: 50, right: 20, bottom: 30, left: 40},
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

  let xUp = d3.scaleLinear().range([0, width]);
  let yUp = d3.scaleLinear().range([height, 0]);

  let tooltip = d3.select("body").append("div")
        .attr("class", "toolTip")
        .style("display", "none");

  let svg = d3.select('.svgPlot');

  d3.json(`../assets/data/${Params.type}${Params.Year}.json`, (error, data) => {
    if (error) throw error;

    const refinedData = parametrize(data, Params);

    refinedData.forEach((d) => {
      d[Params.xSelect] = Number(d[Params.xSelect]);
      d[Params.ySelect] = Number(d[Params.ySelect]);
    });

    let min = d3.min(refinedData,(d) => d[Params.xSelect]);
    xUp.domain([(min - 2 <= 0 ? 0 : min - 2),
              d3.max(refinedData,(d) => d[Params.xSelect])]);
    yUp.domain([0, d3.max(refinedData,(d) => d[Params.ySelect])]);

    svg.select('.x-axis')
       .transition()
       .duration(1000)
       .call(d3.axisBottom(xUp));


    svg.select('.y-axis')
      .transition()
      .duration(1000)
       .call(d3.axisLeft(yUp));


    svg.select('#xlabel')
    .text(`${Params.xSelect}`);

    svg.select('#ylabel')
      .text(`${Params.ySelect}`);


    let circle = svg.selectAll("circle")
                    .data(refinedData);


    circle.exit()
          .transition()
          .remove();

    circle.transition()
      .duration(1000)
      .attr("r", 5)
      .attr("cx", (d) =>  xUp((d[Params.xSelect])) )
      .attr("cy", (d) => yUp((d[Params.ySelect])) );


    circle.enter().append("circle")
        .attr('id', (d) => `${d.Player}`)
        .attr("r", 5)
        .attr("cx", (d) => xUp((d[Params.xSelect])) )
        .attr("cy", (d) => yUp((d[Params.ySelect])) );

       });
}

1 个答案:

答案 0 :(得分:0)

您的第一组圈子会附加到已翻译的组:

let svg = d3.select('.plot').append("svg")
  .attr('class', 'svgPlot')
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform","translate(" + margin.left + "," + margin.top + ")");

在这种情况下,svg变量指的是已翻译的组。但是,当您稍后重新选择时,实际上会附加到根SVG元素:

  let svg = d3.select('.svgPlot');

这是差异的起源。