zoomable d3折线图已经消失了数据

时间:2014-07-30 15:39:35

标签: javascript d3.js

我正在尝试为我使用自定义数据对象构建的历史折线图添加缩放功能。我一直在使用http://codepen.io/brantwills/pen/igsoc/作为模板。图表已呈现,但当我尝试缩放时,有两个错误:

错误:路径属性d =“”的值无效 未捕获的TypeError:undefined不是一个函数(在最后一个转换中,转换为缩放函数的最后一部分)

JSFiddle:http://jsfiddle.net/dshamis317/sFp6Q/

这就是我的代码:

function renderHistoricalData(data) {
  var parseDate = d3.time.format("%Y%m%d").parse;

  data.forEach(function(d) { d.date = parseDate(d.date); });
  // data.sort(function(a,b) { return a.date - b.date; });

  var margin = {top: 20, right: 80, bottom: 30, left: 50},
  width = 1200 - margin.left - margin.right,
  height = 450 - margin.top - margin.bottom;

  var x = d3.time.scale()
    .range([0, width]);

  var y = d3.scale.linear()
    .range([height, 0]);

  var color = d3.scale.category10();

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

  var zoom = d3.behavior.zoom()
    .x(x)
    .y(y)
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

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

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

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

  var sites = color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {date: d.date, sentiment: +d[name]};
      })
    };
  });

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

  y.domain([
    d3.min(sites, function(c) { return d3.min(c.values, function(v) { return v.sentiment; }); }),
    d3.max(sites, function(c) { return d3.max(c.values, function(v) { return v.sentiment; }); })
    ]);

  var site = svg.selectAll(".site")
    .data(sites)
    .enter().append("g")
      .attr("class", "site");

  site.append("path")
    .attr("class", "line")
    .attr("d", function(d) { return line(d.values); })
    .style("stroke", function(d) { return color(d.name); });

  site.append("text")
    .attr("transform", function(d) {
        var val = d.values[d.values.length-1];
        return "translate(" + x(val.date) + "," + y(val.sentiment) + ")";
    })
    .attr("x", 3)
    .attr("dy", ".35em")
        .style("text-anchor", "start")
        .text(function(d) { return d.name; });

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

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Sentiment (%)");

  function zoomed() {
    svg.select(".x.axis").call(xAxis);
    svg.select(".y.axis").call(yAxis);
    svg.selectAll('path.line').attr('d', line);

    sites.selectAll('.site').attr("transform", function(d) {
      return "translate(" + x(d.date) + "," + y(d.sentiment) + ")"; }
    );
  }
}

谢谢!

1 个答案:

答案 0 :(得分:2)

好的,让我们一起来看看。

首先,在zoomed中,最后一次转换不需要在那里。在原版中,它可以移动您没有的圆圈。

同样重要的是,您在path.line上的修改会将d设置为错误的功能。如果您在第一次创建时查看自己设置d的内容,那么它应该是相同的,作为一般经验法则,因此它应该是function(d) { return line(d.values); },而不仅仅是line }。

现在,由于实际原因,它正在消失。

您的比例范围是根据原始域计算的。但是,您在调用scaleExtent之后才设置域,这意味着您的缩放都是基于默认值。它实际上并没有消失,而是被压缩到图的左侧。如果您移除x轴,您将看到所有数据的彩色污迹在侧面变平。

将您的所有域计算移动到您构建比例的上方,这样就可以了。

使事情更具体:

function renderHistoricalData(data) {
  var parseDate = d3.time.format("%Y%m%d").parse;

  data.forEach(function(d) { d.date = parseDate(d.date); });
  // data.sort(function(a,b) { return a.date - b.date; });

  var margin = {top: 20, right: 80, bottom: 30, left: 50},
  width = 1200 - margin.left - margin.right,
  height = 450 - margin.top - margin.bottom;

  var x = d3.time.scale()
    .range([0, width]);

  var y = d3.scale.linear()
    .range([height, 0]);

  var color = d3.scale.category10();

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

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

  var sites = color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {date: d.date, sentiment: +d[name]};
      })
    };
  });

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

  y.domain([
    d3.min(sites, function(c) { return d3.min(c.values, function(v) { return v.sentiment; }); }),
    d3.max(sites, function(c) { return d3.max(c.values, function(v) { return v.sentiment; }); })
    ]);

  var zoom = d3.behavior.zoom()
    .x(x)
    .y(y)
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

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

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

  var site = svg.selectAll(".site")
    .data(sites)
    .enter().append("g")
      .attr("class", "site");

  site.append("path")
    .attr("class", "line")
    .attr("d", function(d) { return line(d.values); })
    .style("stroke", function(d) { return color(d.name); });

  site.append("text")
    .attr("transform", function(d) {
        var val = d.values[d.values.length-1];
        return "translate(" + x(val.date) + "," + y(val.sentiment) + ")";
    })
    .attr("x", 3)
    .attr("dy", ".35em")
        .style("text-anchor", "start")
        .text(function(d) { return d.name; });

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

  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Sentiment (%)");

  function zoomed() {
    svg.select(".x.axis").call(xAxis);
    svg.select(".y.axis").call(yAxis);
    svg.selectAll('path.line').attr('d', function(d) { return line(d.values); });
  }
}

如果您想要移动文字,可以给它一个易于识别的类,然后在zoomed中更新。

给它上课:

site.append( “文本”)     .attr(“class”,“lineLabel”)

zoomed中更新它:

svg.selectAll(".lineLabel")
.attr("transform", function(d) {
    var val = d.values[d.values.length-1];
    return "translate(" + x(val.date) + "," + y(val.sentiment) + ")";
});

这只会让它跟随行的末尾,但你可以修改你喜欢的任何属性来获得想要的效果。