使用d3和从rails传递的JSON数据对象绘制一条线

时间:2013-11-20 13:56:52

标签: ruby-on-rails json d3.js

我在这里推动经验的界限,无法看到我做错了什么。

我从rails中的数据库中提取了大量数据,将其转换为JSON并尝试在d3中绘制它。

数据是{date =>的简单JSON。数字},数据很好。

我在代码底部的循环中对d3做错了什么但是看不清楚。

轴线很好但我无法画线。

这是我的代码:

var data = <%= @signups.to_json.html_safe %>;

var date, signups

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

var parseDate = d3.time.format("%d-%b-%Y").parse;

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

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

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

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

var line = d3.svg.line()
    .x(date)
    .y(signups)
    .interpolate("linear");

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

// Find range of data for domain
var min_date = Infinity, max_date = -Infinity;
var min_signups = Infinity, max_signups = -Infinity;
var x;

$.each(data, function(key, value) {

    temp = parseDate(key)
    if( temp < min_date) min_date = temp;
    if( temp > max_date) max_date = temp;

    if( +value < min_signups) min_signups = +value;
    if( +value > max_signups) max_signups = +value;

});

x.domain([min_date, max_date]);
y.domain([0, max_signups]);

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("Price ($)");

svg.append("path")

$.each(data, function(key, value) {
    date = parseDate(key);
    signups = value;

    d3.select("path")
    .append("svg")
    .attr("d", d3.svg.line()
        .x(date)
        .y(signups)
        .interpolate("linear"));    
});

非常感谢任何帮助

1 个答案:

答案 0 :(得分:1)

D3方式是将所有数据传递给合适的线路生成器。在您的情况下,这非常简单,您只需要将包含所有数据的对象转换为D3可以使用d3.entries()处理的数组。

var line = d3.svg.line()
             .x(function(d) { return x(parseDate(d.key)); })
             .y(function(d) { return y(d.value); });
svg.selectAll("path").data([d3.entries(data)])
   .enter().append("path").attr("d", line);

由于您只有一行,您还可以使用.datum()来绑定数据,但使用.data()可以选择在以后传递更多行的数据。

完成jsfiddle here。修改此项时,请确保在添加轴之前创建行,否则D3的数据匹配将无法使用默认匹配,您将无法获得任何行。要解决这个问题,你可以提供一个匹配的功能,但是从这开始就更容易保持这个顺序。