Как конвертировать D3js V2 в V4? - PullRequest
0 голосов
/ 23 ноября 2018

Я попытался перенести D3js V2 в V4 из приведенного ниже примера:

https://jasonneylon.wordpress.com/2013/09/05/two-sided-horizontal-barchart-using-d3-js/

Но при миграции произошла ошибка: Ошибка: атрибут y: ожидаемая длина, "NaN".

в строке № 201: .attr ("y", функция (d, z) {return y (z) + y.bandwidth () / 2;}) и строка № 223: .attr ("y", function (d) {return y (d) + y.bandwidth () / 2;}

Пожалуйста, совет.

<!DOCTYPE html>
<html>
<head>
<title>Bar Chart</title>
<script src="http://d3js.org/d3.v4.js"></script>
<style type="text/css">
.chart {
  background: #00ccff;
  margin: 10px;
  padding-top: 10px; 
}
.chart .right {
  stroke: white;
  fill: indianred; 
}
.chart .left {
  stroke: white;
  fill: steelblue; 
}
.chart rect:hover {
  fill: #64707d; 
}
.chart text {
  fill: white; 
}
.chart text.name {
  fill: black; 
}
</style>
</head>
<body>
<h1>Two sided horiztontal bar chart</h1>
<script type="text/javascript">
  var randomNumbers = function() { 
    var numbers = [];
    for (var i = 0; i < 20; i++) {
      numbers.push(parseInt(Math.random() * 19) + 1);
    }
    return numbers;
  };

  var randomNames = function() { 
    var names = [];
    for (var i = 0; i < 20; i++) {
      names.push(String.fromCharCode(65 + Math.random() * 25) + String.fromCharCode(65 + Math.random() * 25) + String.fromCharCode(65 + Math.random() * 25));
    }
    return names;
  };

  var names = randomNames();
  var leftData = randomNumbers();  
  var rightData = randomNumbers();

  for (var i= 0; i< names.length; i++) {
    console.log(names[i] + " from: " + leftData[i] + " to: " + rightData[i]);  
  }
  var labelArea = 160;
  var chart,
      width = 400,
      bar_height = 20,
      height = bar_height * (names.length);
  var rightOffset = width + labelArea;
  var chart = d3.select("body")
    .append('svg')
    .attr('class', 'chart')
    .attr('width', labelArea + width + width)
    .attr('height', height);

  var xFrom = d3.scaleLinear()
     .domain([0, d3.max(leftData)])
     .range([0, width]);

  var y = d3.scaleBand()
     .domain(names)
     .rangeRound([10, height]);
    console.log('Y Range: '+y.range());
    console.log('y.bandwidth(): '+y.bandwidth()); // 33

  var yPosByIndex = function(d, index){ return y(index); } 
  chart.selectAll("rect.left")
    .data(leftData)
    .enter().append("rect")
    .attr("x", function(pos) { return width - xFrom(pos); })
    .attr("y", yPosByIndex)
    .attr("class", "left")
    .attr("width", xFrom)
    .attr("height", y.bandwidth()); 

  chart.selectAll("text.leftscore")
    .data(leftData)
    .enter().append("text")
    .attr("x", function(d) { return width - xFrom(d); })
    .attr("y", function(d, z){ return y(z) + y.bandwidth()/2; } )
    .attr("dx", "20")
    .attr("dy", ".36em")
    .attr("text-anchor", "end")
    .attr('class', 'leftscore')
    .text(String);

  chart.selectAll("text.name")
    .data(names)
    .enter().append("text")
    .attr("x", (labelArea / 2) + width)
    .attr("y", function(d){ return y(d) + y.bandwidth()/2; } )
    .attr("dy", ".20em")
    .attr("text-anchor", "middle")
    .attr('class', 'name')
    .text(String);

  var xTo = d3.scaleLinear()
     .domain([0, d3.max(rightData)])
     .range([0, width]);

  chart.selectAll("rect.right")
    .data(rightData)
    .enter().append("rect")
    .attr("x", rightOffset)
    .attr("y", yPosByIndex)
    .attr("class", "right")
    .attr("width", xTo)
    .attr("height", y.bandwidth()); 

  chart.selectAll("text.score")
    .data(rightData)
    .enter().append("text")
    .attr("x", function(d) { return xTo(d) +  rightOffset; })
    .attr("y", function(d,z){ console.log(y(z)); return y(z) + y.bandwidth()/2; } )
    .attr("dx", -5)
    .attr("dy", ".36em")
    .attr("text-anchor", "end")
    .attr('class', 'score')
    .text(String);
</script>
</body>
</html>

1 Ответ

0 голосов
/ 23 ноября 2018

Вы звоните console.log(y(z)); и получаете 40 undefined.И вы не расследуете почему?

Что такое домен y? Строки

Так что, если вы дадите ему число, оно, скорее всего, даст вам неправильный ответ.

По той же причине, по которой ваша функция

var yPosByIndex = function(d, index){ return y(index); }

неправильно.

Основная причина возникновения всех этих проблем заключается в том, что у вас есть несколько массивов информации, связанных на основе индекса.Создайте 1 массив с объектами, которые содержат все связанные данные.

var data = d3.range(20).map(i => { return {name: randomName(), left:randomNumber(), right:randomNumber()}; } );

Теперь настройте вашу программу на использование d.name, d.left, d.right.

Не использовать parseInt Если вы хотите вычислить целую часть числа, это медленно и неясно, что вы хотите, используйте Math.floor()

Лучше использовать один и тот же xScale для левой и правой полос.Почему полоса со значением 10 должна быть меньше с одной из сторон?

...