Помогите найти ошибку в проложении для построения графиков D3

184
25 марта 2018, 22:57

Приветствую. Пишу приложение на D3 + jQuery. Оно должно строить различные графики. Информация приходит либо из формы ввода, либо из файла. Столкнулся с проблемой, по какой-то причине приложение соединяет линией первую и последнюю точку графика, таким образом замыкая его. Мне это вовсе не ненужно. Помогите разобраться с проблемой.

Мой код

//Добавления строки таблицы 
 
$('.btn').click(function() { 
  var ind = $('tr:last').index(); 
  $('.hide').clone().appendTo('table').addClass('row').removeClass('hide'); 
  $('tr:last>td:nth-child(2)>input').addClass('x'); 
  $('tr:last>td:nth-child(3)>input').addClass('y'); 
  $('tr:last>td:first').text(ind); 
  data = []; 
}); 
 
var rawData = []; 
height = 500, 
  width = 500, 
  margin = 50, 
  data = [], 
  numb, 
  x, y, 
  mass = {}, 
  info; 
 
//функция построения сетки координат 
 
var osi = function() { 
  var cur = 0; 
 
  // создание объекта svg 
  var svg = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
 
  // длина оси X= ширина контейнера svg - отступ слева и справа 
  var xAxisLength = width - 2 * margin; 
 
  // длина оси Y = высота контейнера svg - отступ сверху и снизу 
  var yAxisLength = height - 2 * margin; 
 
  for (var i = 0; i < rawData.length; i++) { 
    if (cur < rawData[i].x) { 
      cur = rawData[i].x 
    } 
    if (cur < rawData[i].y) { 
      cur = rawData[i].y 
    } 
  } 
  var sizePlus = cur / 100 * 10; 
  numb = cur + sizePlus; 
 
  // функция интерполяции значений на ось Х   
  var scaleX = d3.scale.linear() 
    .domain([0, numb]) 
    .range([0, xAxisLength]); 
 
  // функция интерполяции значений на ось Y 
  var scaleY = d3.scale.linear() 
    .domain([numb, 0]) 
    .range([0, yAxisLength]); 
 
  // масштабирование реальных данных в данные для нашей координатной системы 
  for (i = 0; i < rawData.length; i++) 
    data.push({ 
      x: scaleX(rawData[i].x) + margin, 
      y: scaleY(rawData[i].y) + margin 
    }); 
 
  // создаем ось X    
  var xAxis = d3.svg.axis() 
    .scale(scaleX) 
    .orient("bottom"); 
  // создаем ось Y              
  var yAxis = d3.svg.axis() 
    .scale(scaleY) 
    .orient("left"); 
 
  for (i = 0; i < rawData.length; i++) 
    data.push({ 
      x: scaleX(rawData[i].x) + margin, 
      y: scaleY(rawData[i].y) + margin 
    }); 
 
  // отрисовка оси Х              
  svg.append("g") 
    .attr("class", "x-axis") 
    .attr("transform", // сдвиг оси вниз и вправо 
      "translate(" + margin + "," + (height - margin) + ")") 
    .call(xAxis); 
 
  // отрисовка оси Y  
  svg.append("g") 
    .attr("class", "y-axis") 
    .attr("transform", // сдвиг оси вниз и вправо на margin 
      "translate(" + margin + "," + margin + ")") 
    .call(yAxis); 
 
  // создаем набор вертикальных линий для сетки    
  d3.selectAll("g.x-axis g.tick") 
    .append("line") 
    .classed("grid-line", true) 
    .attr("x1", 0) 
    .attr("y1", 0) 
    .attr("x2", 0) 
    .attr("y2", -(yAxisLength)); 
 
  // рисуем горизонтальные линии координатной сетки 
  d3.selectAll("g.y-axis g.tick") 
    .append("line") 
    .classed("grid-line", true) 
    .attr("x1", 0) 
    .attr("y1", 0) 
    .attr("x2", xAxisLength) 
    .attr("y2", 0); 
} 
 
//функция которая читает значение переменных и записывает из в масив.  
 
var inputToMass = function() { 
  data = []; 
  var inpx = $('.x'); 
  var inpy = $('.y'); 
  var massx = []; 
  var massy = []; 
  for (i = 0; i < inpx.length; i++) { 
    mass = {}; 
    x = inpx[i].value; 
    x = parseInt(x); 
    mass.x = x; 
    y = inpy[i].value; 
    y = parseInt(y); 
    mass.y = y; 
    rawData[i] = mass; 
  } 
  for (i = 0; inpx.length > i; i++) { 
    x = inpx[i].value; 
    x = parseInt(x); 
    massx[i] = x; 
    y = inpy[i].value; 
    y = parseInt(y); 
    massy[i] = y; 
  } 
} 
 
// общая функция которая при нажатии на кнопку вызывает остальные функции 
 
$('.btn2').click(function() { 
  $('svg').remove(); 
  inputToMass(); 
  osi(); 
  chart1(); 
}); 
 
// функция чтения из файла 
 
$('.file').change(function() { 
  var fr = new FileReader(); 
  fr.onload = function(info) { 
    var rezf = info.target.result; 
    $('svg').remove(); 
    data = []; 
    rawData = JSON.parse(rezf); 
    osi(); 
    chart1() 
    console.log(data); 
  } 
  fr.readAsText(this.files[0]); 
}); 
 
//функция построения графика #1 
 
var chart1 = function() { 
  // создание объекта svg 
  var svg = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
 
  // функция, создающая по массиву точек линии 
  var line = d3.svg.line() 
    .x(function(d) { 
      return d.x; 
    }) 
    .y(function(d) { 
      return d.y; 
    }); 
 
  // добавляем путь 
  svg.append("g").append("path") 
    .attr("d", line(data)) 
    .style("stroke", "steelblue") 
    .style("stroke-width", 2); 
} 
 
//функция построения графика #2 
 
var chart2 = function() { 
 
  var svg = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
  // функция, создающая по массиву точек линии 
  var line = d3.svg.line() 
    .x(function(d) { 
      return d.x; 
    }) 
    .y(function(d) { 
      return d.y; 
    }); 
  // функция, создающая область 
  var area = d3.svg.area() 
    .x(function(d) { 
      return d.x; 
    }) 
    .y0(height - margin) 
    .y1(function(d) { 
      return d.y; 
    }); 
 
  var g = svg.append("g"); 
  g.append("path") 
    .attr("d", area(data)) 
    .style("fill", "lightblue"); 
  g.append("path") 
    .attr("d", line(data)) 
    .style("stroke", "steelblue") 
    .style("stroke-width", 2); 
} 
 
//функция построения графика #3 
 
var chart3 = function() { 
  var svg = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
 
  var line = d3.svg.line().interpolate("basis") 
    .x(function(d) { 
      return d.x; 
    }) 
    .y(function(d) { 
      return d.y; 
    }); 
 
  var area = d3.svg.area().interpolate("basis") 
    .x(function(d) { 
      return d.x; 
    }) 
    .y0(height - margin) 
    .y1(function(d) { 
      return d.y; 
    }); 
 
  var g = svg.append("g"); 
  g.append("path") 
    .attr("d", area(data)) 
    .style("fill", "lightblue"); 
  g.append("path") 
    .attr("d", line(data)) 
    .style("stroke", "steelblue") 
    .style("stroke-width", 2); 
}
<body> 
 
  <div class="table"> 
    <table border="1"> 
      <tr> 
        <th>#</th> 
        <th>X</th> 
        <th>Y</th> 
      </tr> 
      <tr class="hide"> 
        <td></td> 
        <td><input type="number"></td> 
        <td><input type="number"></td> 
      </tr> 
      <tr class="row"> 
        <td>1</td> 
        <td><input class="x" type="number"></td> 
        <td><input class="y" type="number"></td> 
      </tr> 
    </table> 
  </div> 
 
  <br><br> 
 
  <button class="btn">Add Row</button> 
 
  <button class="btn2">generate</button> 
 
  <input class="file" type="file"> 
 
  <pre class="cont"></pre> 
 
  <button class="btnhelp">HELP</button> 
 
</body>

Answer 1

Вы два раза в массив data добавляли координаты. Исправил пример и подкорректировал параметры svg. Пример рабочий.

//Добавления строки таблицы 
 
$('.btn').click(function() { 
  var ind = $('tr:last').index(); 
  $('.hide').clone().appendTo('table').addClass('row').removeClass('hide'); 
  $('tr:last>td:nth-child(2)>input').addClass('x'); 
  $('tr:last>td:nth-child(3)>input').addClass('y'); 
  $('tr:last>td:first').text(ind); 
  data = []; 
}); 
 
var rawData = []; 
var svg1; 
height = 500, 
  width = 500, 
  margin = 50, 
  data = [], 
  numb=0, 
  x=0, y=0, 
  mass = {}, 
  info=0; 
 
//функция построения сетки координат 
 
var osi = function() { 
  var cur = 0; 
 
  // создание объекта svg 
  svg1 = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
 
  // длина оси X= ширина контейнера svg - отступ слева и справа 
  var xAxisLength = width - 2 * margin; 
 
  // длина оси Y = высота контейнера svg - отступ сверху и снизу 
  var yAxisLength = height - 2 * margin; 
 
  for (var i = 0; i < rawData.length; i++) { 
    if (cur < rawData[i].x) { 
      cur = rawData[i].x 
    } 
    if (cur < rawData[i].y) { 
      cur = rawData[i].y 
    } 
  } 
  var sizePlus = cur / 100 * 10; 
  numb = cur + sizePlus; 
 
  // функция интерполяции значений на ось Х   
  var scaleX = d3.scale.linear() 
    .domain([0, numb]) 
    .range([0, xAxisLength]); 
 
  // функция интерполяции значений на ось Y 
  var scaleY = d3.scale.linear() 
    .domain([numb, 0]) 
    .range([0, yAxisLength]); 
 
  // масштабирование реальных данных в данные для нашей координатной системы 
  for (i = 0; i < rawData.length; i++) 
    data.push({ 
      x: scaleX(rawData[i].x) + margin, 
      y: scaleY(rawData[i].y) + margin 
    }); 
 
  // создаем ось X    
  var xAxis = d3.svg.axis() 
    .scale(scaleX) 
    .orient("bottom"); 
  // создаем ось Y              
  var yAxis = d3.svg.axis() 
    .scale(scaleY) 
    .orient("left"); 
 
  // отрисовка оси Х              
  svg1.append("g") 
    .attr("class", "x-axis") 
    .attr("transform", // сдвиг оси вниз и вправо 
      "translate(" + margin + "," + (height - margin) + ")") 
    .call(xAxis); 
 
  // отрисовка оси Y  
  svg1.append("g") 
    .attr("class", "y-axis") 
    .attr("transform", // сдвиг оси вниз и вправо на margin 
      "translate(" + margin + "," + margin + ")") 
    .call(yAxis); 
 
  // создаем набор вертикальных линий для сетки    
  d3.selectAll("g.x-axis g.tick") 
    .append("line") 
    .classed("grid-line", true) 
    .attr("x1", 0) 
    .attr("y1", 0) 
    .attr("x2", 0) 
    .attr("y2", -(yAxisLength)); 
 
  // рисуем горизонтальные линии координатной сетки 
  d3.selectAll("g.y-axis g.tick") 
    .append("line") 
    .classed("grid-line", true) 
    .attr("x1", 0) 
    .attr("y1", 0) 
    .attr("x2", xAxisLength) 
    .attr("y2", 0); 
} 
 
//функция которая читает значение переменных и записывает из в масив.  
 
var inputToMass = function() { 
  data = []; 
  var inpx = $('.x'); 
  var inpy = $('.y'); 
  var massx = []; 
  var massy = []; 
  for (i = 0; i < inpx.length; i++) { 
    mass = {}; 
    x = inpx[i].value; 
    x = parseInt(x); 
    mass.x = x; 
    y = inpy[i].value; 
    y = parseInt(y); 
    mass.y = y; 
    rawData[i] = mass; 
  } 
 
   
  for (i = 0; inpx.length > i; i++) { 
    x = inpx[i].value; 
    x = parseInt(x); 
    massx[i] = x; 
    y = inpy[i].value; 
    y = parseInt(y); 
    massy[i] = y; 
  } 
   
 
} 
 
// общая функция которая при нажатии на кнопку вызывает остальные функции 
 
$('.btn2').click(function() { 
  $('svg').remove(); 
  inputToMass(); 
  osi(); 
  chart1(); 
}); 
 
// функция чтения из файла 
 
$('.file').change(function() { 
  var fr = new FileReader(); 
  fr.onload = function(info) { 
    var rezf = info.target.result; 
    $('svg').remove(); 
    data = []; 
    rawData = JSON.parse(rezf); 
    osi(); 
    chart1(); 
    //console.log(data); 
  } 
  fr.readAsText(this.files[0]); 
}); 
 
//функция построения графика #1 
 
var chart1 = function() { 
  // создание объекта svg 
  //  var svg = d3.select("body").append("svg") 
  //  console.log (rawData); 
  //  console.log (data); 
  // функция, создающая по массиву точек линии 
  var line = d3.svg.line() 
    .x(function(d) { 
      return d.x; 
    }) 
    .y(function(d) { 
      return d.y; 
    }); 
 
  // добавляем путь 
  svg1.append("g").append("path") 
    .attr("d", line(data)) 
    .style("stroke", "steelblue") 
    .style("stroke-width", 2) 
    .style("fill","none"); 
     
     
} 
 
/* 
//функция построения графика #2 
 
var chart2 = function() { 
 
  var svg = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
  // функция, создающая по массиву точек линии 
  var line = d3.svg.line() 
    .x(function(d) { 
      return d.x; 
    }) 
    .y(function(d) { 
      return d.y; 
    }); 
  // функция, создающая область 
  var area = d3.svg.area() 
    .x(function(d) { 
      return d.x; 
    }) 
    .y0(height - margin) 
    .y1(function(d) { 
      return d.y; 
    }); 
 
  var g = svg.append("g"); 
  g.append("path") 
    .attr("d", area(data)) 
    .style("fill", "lightblue"); 
  g.append("path") 
    .attr("d", line(data)) 
    .style("stroke", "steelblue") 
    .style("stroke-width", 2); 
} 
 
//функция построения графика #3 
 
var chart3 = function() { 
  var svg = d3.select("body").append("svg") 
    .attr("class", "axis") 
    .attr("width", width) 
    .attr("height", height); 
 
  var line = d3.svg.line().interpolate("basis") 
    .x(function(d) { 
      return d.x; 
    }) 
    .y(function(d) { 
      return d.y; 
    }); 
 
  var area = d3.svg.area().interpolate("basis") 
    .x(function(d) { 
      return d.x; 
    }) 
    .y0(height - margin) 
    .y1(function(d) { 
      return d.y; 
    }); 
 
  var g = svg.append("g"); 
  g.append("path") 
    .attr("d", area(data)) 
    .style("fill", "lightblue"); 
  g.append("path") 
    .attr("d", line(data)) 
    .style("stroke", "steelblue") 
    .style("stroke-width", 2);  
} */
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="table"> 
    <table border="1"> 
      <tr> 
        <th>#</th> 
        <th>X</th> 
        <th>Y</th> 
      </tr> 
      <tr class="hide"> 
        <td></td> 
        <td><input type="number"></td> 
        <td><input type="number"></td> 
      </tr> 
      <tr class="row"> 
        <td>1</td> 
        <td><input class="x" type="number"></td> 
        <td><input class="y" type="number"></td> 
      </tr> 
    </table> 
  </div> 
 
  <br><br> 
 
  <button class="btn">Add Row</button> 
 
  <button class="btn2">generate</button> 
 
  <input class="file" type="file"> 
 
  <pre class="cont"></pre> 
 
  <button class="btnhelp">HELP</button> 
 
</body>

READ ALSO
Vue CapsLock включен ли как узнать?

Vue CapsLock включен ли как узнать?

Как узнать включен ли Caps Lock при вводе пароля?

167
Из-за js перестаёт работать кнопка

Из-за js перестаёт работать кнопка

Есть js файл без него перестаёт нажиматься кнопка "Оформить заказ" и при нажатии ничего не происходит, если подключу обратно то будет работать...

157
javascript, цепочка промисов для setTimeout

javascript, цепочка промисов для setTimeout

Изучаю промисыПодскажите, пожалуйста, как выполнить такую задачу: Вывод даты через секунду после начала выполнения, потом через 2, потом через...

200