2014-07-25 53 views
1

我目前正在运行一个页面,该页面会在加载页面时生成具有默认值的图形。该页面从PHP脚本生成的TSV中获取数据,并通过GET参数进行修改。删除d3.js中的前一个路径并转换为新数据

用户可以输入选项,并通过AJAX更新图形。

目前该页面几乎可以正常工作,但它是用新数据覆盖新路径而不删除旧路径。

新数据具有相同的x范围和域但不同的y坐标值,有时具有不同数量的值。

理想情况下,我希望旧路径从旧路径流畅地过渡 - 我如何使这种情况发生?

我试着在下面包含相关代码。对于质量差的道歉,我对d3非常陌生。

... 

var line = d3.svg.line() 
    .interpolate("basis") 
    .defined(function(d) { 
     return d.result != 0; 
    }) 
    .x(function(d) { 
     return x(d.date); 
    }) 
    .y(function(d) { 
     return y(d.result); 
    }); 

var svg = d3.select(".chart") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

var txtDays = 7; 
var txtStartDate = "01/01/2013"; 
var txtEndDate = "01/01/2014"; 
var txtInterval = 1; 

requestDataURL = //removed for SO 


    d3.tsv("http://localhost" + requestDataURL, function(error, data) { 
     var varPolls = d3.keys(data[0]).filter(function(key) { 
      return key !== "date"; 
     }); 

     data.forEach(function(d) { 
      d.date = parseDate(d.date); 
     }); 

     var results = varPolls.map(function(name) { 
      return { 
       name: name, 
       values: data.map(function(d) { 
        return { 
         date: d.date, 
         result: +d[name] 
        }; 
       }) 
      }; 
     }); 


     x.domain(d3.extent(data, function(d) { 
      return d.date; 
     })); 



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

     svg.append("g") 
      .attr("class", "y axis") 
      .call(yAxis) 

     var group = svg.selectAll(".group") 
      .data(results) 
      .enter().append("g") 
      .attr("class", "group") 
      .attr("data-name", function(d) { 
       return d.name; 
      }); 

     group.append("path") 
      .attr("class", "line") 
      .attr("d", function(d) { 
       return line(d.values); 
      }) 
      .style("stroke", function(d) { 
       return colors[d.name]; 
      }); 

     group.append("text") 
      .datum(function(d) { 
       return { 
        name: d.name, 
        value: d.values[d.values.length - 1] 
       }; 
      }) 
      .attr("transform", function(d) { 
       return "translate(" + x(d.value.date) + "," + y(d.value.result) + ")"; 
      }) 
      .attr("x", 3) 
      .attr("dy", ".35em") 
      .text(function(d) { 
       return Math.round(d.value.result);; 
      }); 

     d3.select(".submit") 
      .attr('disabled', null); 


    }); 

$(".submit").click(function(event) { 
    var data = []; 
    //SORT OUT VALIDATION 


    var req = $.ajax({ 
     url: requestDataURL, 
     dataType: 'text', 
     success: function(response) { 
      data = response; 
     } 
    }); 

    requestDataURL = //new data removed for SO 

     $.when(req).done(function() { 
      d3.tsv("http://localhost" + requestDataURL, function(error, data) { 

       var varPolls = d3.keys(data[0]).filter(function(key) { 
        return key !== "date"; 
       }); 

       data.forEach(function(d) { 
        d.date = parseDate(d.date); 
       }); 

       var results = varPolls.map(function(name) { 
        return { 
         name: name, 
         values: data.map(function(d) { 
          return { 
           date: d.date, 
           result: +d[name] 
          }; 
         }) 
        }; 
       }); 


       x.domain(d3.extent(data, function(d) { 
        return d.date; 
       })); 


       var group = svg.selectAll(".chart") 
        .data(results); 

       group.exit().remove(); 

       group.enter().append("g"); 
       group.attr("class", "group") 
        .attr("data-name", function(d) { 
         return d.name; 
        }); 

       group.append("path") 
        .attr("class", "line") 
        .attr("d", function(d) { 
         return line(d.values); 
        }) 
        .style("stroke", function(d) { 
         return colors[d.name]; 
        }); 




       group.transition() 
        .duration(500) 
        .ease("linear") 
        .attr("d", group); 

      }); 

     }); 
}); 

回答

1

问题是您没有正确处理输入和更新选择。通常,追加操作只应发生在输入选择上,而不是更新。当你获得新的数据,你有下面的代码:

group.enter().append("g"); 
// ... 
group.append("path"); 

这将追加新path元素,以更新选择,这是你在图中看到的。处理新数据将如下的正确方法如下:

var enterSel = group.enter().append("g"); 
// set attributes on the g elements 
enterSel.append("path"); // append path elements to the new g elements 

group.select("path") // select the path elements that are present, this includes the newly appended ones 
    .attr("d", function(d) { // update the d attribute 
     return line(d.values); 
    }); 

该代码将追加对没有对应元素和现有元素更新path数据项目新的元素。

+0

感谢您的帮助,我当然在概念上对d3感到困惑。我试过这个,但无济于事。最初有4个g元素,每个元素都有一个路径,程序仍然追加4 g元素而没有正确的新路径。 – tom

+1

啊,看起来你的选择器应该是'.group'而不是'.chart'。我会建议重构代码以消除这种重复并避免这样的问题。 –

+0

很好,非常感谢!应该看到我自己。重构是下一步非常需要的,只是非常渴望呈现原型。 – tom