agentv
agentv

Reputation: 779

D3 Line and Path - graph line doesn't show

...I'm porting a graph over from v3 to v4 and I've hit a wall with respect to path and line.

Here's what I believe to be the salient section:

<script src="https://d3js.org/d3.v4.min.js"></script>
pdata = [
        {
            "date": "2018-01-01",
            "marketPrice": 3131
        },
        {
            "date": "2018-01-02",
            "marketPrice": 3151
        }
];  

// loop that transforms "date" to new Date(), marketPrice to numeric 
// *** added during edit ***

// format the data
pdata.forEach(function(d) {
  d.date = new Date (d.date); // difference between this and Ref(3) is...
    // ref(3) calls a time parser rather than instantiate new Date()
  d.marketPrice = +d.marketPrice;
  //console.log("parsing date into: -- Date: " + d.date + " -- Market Price: " + d.marketPrice);
});

// linear scaling functions - xscale() and yscale()
// *** added during edit ***

// Create scales (added in edit)
var xscale = d3.scaleTime()
      .domain([
        d3.min(pdata, function (d){return d.date}), 
        d3.max(pdata, function (d){return d.date})
      ])
      .range([GRAPHLEFT, GRAPHRIGHT]);

var yscale = d3.scaleLinear()
      .domain([
        d3.min(pdata, function (d){return d.marketPrice}), 
        d3.max(pdata, function (d){return d.marketPrice})
      ])
      .range([GRAPHBOTTOM,GRAPHTOP]);

// axis functions omitted ...these work predictably

svg.append("path")
    .data([pdata])
    .attr("stroke", "steelblue")
    .attr("stroke-width", 3)
    .attr("fill", "none")
    .attr("d", lineFunc);

var lineFunc = d3.line()
  .x(function (d) {
    console.log("Graphing x as: " + xscale(d.date)); // updated during edit
    return (xscale(d.date)); // updated during edit ... reveals as NaN
  })
  .y(function (d) {
    console.log("Graphing y as: " + yscale(d.marketPrice)); // updated during edit ... reveals as NaN
    return (yscale(d.marketPrice));
  });

I can't confirm that the callbacks from lineFunc() are actually getting called. (Now resolved in accord with answer below)

In my page, the axes appear, but no plot line appears.

I'm working from these references and models:

(1) - https://github.com/d3/d3-shape/blob/master/README.md#line

(2) - https://bl.ocks.org/pstuffa/26363646c478b2028d36e7274cedefa6

(3) - https://bl.ocks.org/d3noob/402dd382a51a4f6eea487f9a35566de0

Upvotes: 1

Views: 2547

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

Despite d3.line() being a method (i.e., a function), var lineFunc = d3.line().etc... is a function expression, and, unlike function statement, it's not hoisted:

Function expressions in JavaScript are not hoisted, unlike function declarations. You can't use function expressions before you define them. (MDN source)

Therefore, move var lineFunc = d3.line().etc... to the top, before the .attr("d", lineFunc) for the path:

var lineFunc = d3.line()
    .x(function (d) {
    //etc... 

svg.append("path")
    .data([pdata])
    //etc..
    .attr("d", lineFunc);

PS: You still need a scale in the line generator. Your path will be appended in the SVG, but the x values will be timestamps and the y values the actual marketPrice values.

Upvotes: 2

agentv
agentv

Reputation: 779

...dunno why it took me so long to find the answer, but along the way I had the opportunity to scrub over the D3 API doc and examples with a fine toothed comb.

The final answer is actually supplied above in comments.

I was using data([pdata]) instead of datum(pdata) and when I corrected the code fully, the issue was solved. (For a while, I had datum([pdata]) and that didn't work out for reasons explained in this fine article.

Thanks Gerardo Fudado - and yes, I bought the silly t-shirt.

Upvotes: 1

Related Questions