1

I cannot understand the behaviour of d3 when reading data for diagonal.

Below I read data from my job_small.csv in both the line and diagonal variable. I have put in console.log steps in each.

I comment out either of the last two lines of code to draw either diagonal or line.

When I run to draw line, this scripts runs successfully and the console log prints out 48,48,240,96,384,384.

When I run to draw the diagonal, this script fails. The console.log step shows that the values for x and y are NaN.

I am at a loss to understand what is going on in the diagonal variable where it says it could not read the data object where as the line variable could.

The data in my job_small.csv is : sx,sy,tx,ty\n 1,1,5,5\n 5,2,7,6\n 8,8,17,14

d3.csv("/static/data/job_small.csv", function (data) {
var canvas = d3.select("body").append("svg").attr("width",600).attr("height",600);
var x_scale = d3.scale.linear().domain([0,20]).range([0, 960]);
var y_scale = d3.scale.linear().domain([0,20]).range([300, 0]);

var diagonal = d3.svg.diagonal()
    .source(    function (d) {
        var x=x_scale(d['sx']);
        var y=x_scale(d['sy']);
        var p={};
        p.x=x;
        p.y=y;
        console.log(x)  // When these print, they show Nan
        console.log(y)  // When these print, they show Nan
        return p;
    })
    .target(    function (d) {
        var x=x_scale(d['tx'])
        var y=x_scale(d['ty'])
        var p={};
        p.x=x;
        p.y=y;
        return p;
    });

var line = d3.svg.line()
    .x(function(d) { var x=x_scale(d['sx']);console.log(x); return x; })
    .y(function(d) { var y=x_scale(d['sy']);console.log(y); return y; });
// When I print console for this line var, I get 48,48,240,96,384,384

var path = canvas.append('path').attr('d', diagonal(data));  // Get error
var path = canvas.append('path').attr('d', line(data));   // This runs successfully
});
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • 1
    Naming a SVG tag `canvas` is very confusing because there is a `canvas` tag and that behaves quite different from an SVG. – rioV8 Jul 19 '18 at 13:47

1 Answers1

2

Unlike the line generator, d3.svg.diagonal expect a datum (not data) as the argument.

Therefore, you have to choose what object will be the source and what object will be the target. For instance, let's make the first one the source and the second one the target:

var diagonal = d3.svg.diagonal()
  .source(function(d) {
    var x = x_scale(d[0]['sx']);
    var y = x_scale(d[0]['sy']);
    //first object----^
    var p = {};
    p.x = x;
    p.y = y;
    return p;
  })
  .target(function(d) {
    var x = x_scale(d[1]['tx'])
    var y = x_scale(d[1]['ty'])
    //second object---^
    var p = {};
    p.x = x;
    p.y = y;
    return p;
  });

Here is the working demo:

    var csv = `sx,sy,tx,ty
1,1,5,5
5,2,7,6
8,8,17,14`;

    var data = d3.csv.parse(csv);

    var x_scale = d3.scale.linear().domain([0, 20]).range([0, 960]);
    var y_scale = d3.scale.linear().domain([0, 20]).range([300, 0]);

    var diagonal = d3.svg.diagonal()
      .source(function(d) {
        var x = x_scale(d[0]['sx']);
        var y = x_scale(d[0]['sy']);
        var p = {};
        p.x = x;
        p.y = y;
        return p;
      })
      .target(function(d) {
        var x = x_scale(d[1]['tx'])
        var y = x_scale(d[1]['ty'])
        var p = {};
        p.x = x;
        p.y = y;
        return p;
      });

    var svg = d3.select("body").append("svg").attr("width", 600).attr("height", 600);
    var path = svg.append('path').attr('d', diagonal(data));
path {
  fill: none;
  stroke: black;
  stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171