2014-11-27 4 views
1

Я пытаюсь сделать линейную диаграмму в d3, со временем по оси x. Я использую данные json в переменной. Я использовал функцию d3.time.format() для форматирования времени, но это дает мне выше ошибки. Я изучаю d3, поэтому, пожалуйста, помогите. мой код:Uncaught TypeError: Не удается прочитать свойство 'length' undefined in d3

<div id="viz"></div> 
<script> 

var width = 640; 
var height = 480; 
var margin = {top: 30, right: 20, bottom: 30, left: 50}, 
width = 600 - margin.left - margin.right, 
height = 270 - margin.top - margin.bottom; 

var x = d3.time.scale().range([0, width]); 
var y = d3.scale.linear().domain([height, 0]); 
var xAxis = d3.svg.axis().scale(x).orient("bottom"); 
var yAxis = d3.svg.axis().scale(y).orient("left"); 
var data = [ 
{ "at": "2014-11-18T07:29:03.859Z", "value": 0.553292}, 
{ "at": "2014-11-18T07:28:53.859Z", "value": 0.563292}, 
{ "at": "2014-11-18T07:28:43.859Z", "value": 0.573292}, 
{ "at": "2014-11-18T07:28:33.859Z", "value": 0.583292}, 
{ "at": "2014-11-18T07:28:13.859Z", "value": 0.553292}, 
{ "at": "2014-11-18T07:28:03.859Z", "value": 0.563292}]; 

var line = d3.svg.line() 
.x(function(d, i) { return x(d.x_axis); }) 
.y(function(d, i) { return y(d.y_axis); }) 
.interpolate("linear"); 
var vis = d3.select("#viz") 
.append("svg:svg") 
.attr("width", width + margin.left + margin.right) 
.attr("height", height + margin.top + margin.bottom) 
.append("g").attr("transform","translate(" + margin.left + "," + margin.top + ")"); 
data.forEach(function(d) { 
d.xAxis = d3.time.format("%d-%b-%y").parse(d.xAxis); 
d.yAxis = +d.value; 
}); 

x.domain(d3.extent(data, function(d) { return d.x_axis; })); 
y.domain(d3.extent(data, function(d) { return d.y_axis; })); 

vis.append("g") 
.attr("class", "x axis") 
.attr("transform", "translate(0," + height + ")") 
.call(xAxis); 
vis.append("g") 
.attr("class", "y axis") 
.call(yAxis); 
vis.append("svg:path") 
.datum(data) 
.attr("class", "line") 
.attr("d", line); 

ответ

1

Есть несколько вопросов, в вашем коде, так что я создал новую один ниже с некоторыми комментариями об изменениях.

<style> 
    /* You need some styling for your line */ 
    .line{ 
     stroke:steelblue; 
     fill:none 
    } 
</style> 
<script> 

    var width = 640; 
    var height = 480; 
    var margin = {top: 30, right: 20, bottom: 30, left: 50}, 
    width = 600 - margin.left - margin.right, 
    height = 270 - margin.top - margin.bottom; 

    var x = d3.time.scale().range([0, width]); 
    // You had a mistake filling the domain structure of your scale. 
    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 data = [ 
    { "at": "2014-11-18T07:29:03.859Z", "value": 0.553292}, 
    { "at": "2014-11-18T07:28:53.859Z", "value": 0.563292}, 
    { "at": "2014-11-18T07:28:43.859Z", "value": 0.573292}, 
    { "at": "2014-11-18T07:28:33.859Z", "value": 0.583292}, 
    { "at": "2014-11-18T07:28:13.859Z", "value": 0.553292}, 
    { "at": "2014-11-18T07:28:03.859Z", "value": 0.563292}]; 
    //You were using non existing variables 
    var line = d3.svg.line() 
     .x(function(d) { return x(d.xAxis); }) 
     .y(function(d) { return y(d.yAxis); }) 
     .interpolate("linear"); 

    var vis = d3.select("#viz") 
     .append("svg:svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom) 
     .append("g").attr("transform","translate(" + margin.left + "," + margin.top + ")"); 
    //You are using ISO format, use the correct time parser 
    var iso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ"); 
    data.forEach(function(d) { 
     d.xAxis = iso.parse(d.at); //You were parsing a non existing variable 
     d.yAxis = parseFloat(d.value); //You were parsing a non existing variable 
    }); 
    console.log(data); 

    //The variables for the domain were not correct 
    x.domain(d3.extent(data, function(d) { return d.xAxis; })); 
    y.domain(d3.extent(data, function(d) { return d.yAxis; })); 

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

    vis.append("svg:path").datum(data).attr("class", "line").attr("d", line); 
</script> 

Позвольте мне знать, если это помогает

+0

Спасибо, это полезно. – user1915636

+0

Спасибо, это полезно. На самом деле я пытаюсь сделать линейную диаграмму, в которой входные данные являются потоком с сервера. Формат и значения данных такие же, как я использовал в данных var. Данные из потока постоянно обновляются каждые 10 секунд. Я хочу отображать данные последних 10 монет и хочу обновить график каждые 10 секунд. Мне нужен конечный результат, как в ссылке: http://bl.ocks.org/benjchristensen/2657838. Пожалуйста, предоставьте мне указатели, чтобы сделать диаграмму в d3. Спасибо в Advance – user1915636

+0

Infact я попробовал один и тот же код, заменяя значение переменных данных потоком данных с сервера и запуская код на локальном хосте. Как-то на локальном хосте команда «data.forEach» (функция (d) { d.xAxis = iso.parse (d.at); d.yAxis = parseFloat (d.value); }); "задает ошибку как" Uncaught TypeError: Не удается прочитать свойство "forEach" неопределенного ". Пожалуйста, помогите. – user1915636

1

Вот скрипку, которая показывает, что я думаю, что вы после: http://jsfiddle.net/henbox/n9s542w0/1/

Существовали несколько изменений, чтобы сделать.

Во-первых, есть некоторая несогласованность в том, как вы используете d.y_axis vs d.yAxis (то же самое с x), чтобы установить \ ссылаться на новые элементы, которые вы добавляете в набор данных, который вы хотите построить. Я установил эти ключи в d.y_axis и d.x_axis.

Следующие:

d.xAxis = d3.time.format("%d-%b-%y").parse(d.xAxis); 

Ваш format здесь следует обратиться к формату входного сигнала, а не на выходе, и вы должны быть разбором d.at, а не d.xAxis (см this answer for more), так что вы должны иметь:

d.x_axis = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse(d.at); 

В-третьих, когда вы добавляете линию, вы должны обрабатывать data по-разному. Изменение:

vis.append("svg:path") 
    .datum(data) 
    .attr("class", "line") 
    .attr("d", line); 

в

vis.append("svg:path") 
    .attr("class", "line") 
    .attr("d", line(data)); 

Согласно this similar примеру

И, наконец, вы настраивали домен у дважды, но никогда не установив диапазон. Линия:

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

следует читать

var y = d3.scale.linear().range([height, 0]); 
Смежные вопросы