tompal18
tompal18

Reputation: 1216

d3js does not enter into line function

I would like to draw a line by d3 with below codes.(http://jsfiddle.net/totaljj/L9n7qnv1)

It draws x,y-axis, but does not enter into the line function when appending d attribute.

You can debug on line number 104 to see that the code does not enter into the line function.

Any help would be appreciated.

<!DOCTYPE html>
<html>
<style>
.axis--x path {
    display: none;
}

.line {
    fill: none;
    stroke: steelblue;
    stroke-width: 1.5px;
}
</style>

<body>
    <!-- Page Content -->

    <div>

            <svg width="430" height="250"></svg>
    </div>

    <section>

        <script src="https://d3js.org/d3.v4.min.js"></script>

        <script>

            var data=
            '{"recordsFiltered":5,"raCounts":[{"name":"comp_name","values":[{"date_":"2016","actual":170.0,"DT_RowId":"row_null"},{"date_":"2015","actual":198.0,"DT_RowId":"row_null"},{"date_":"2015","actual":149.0,"DT_RowId":"row_null"},{"date_":"2014","actual":197.0,"DT_RowId":"row_null"},{"date_":"2014","actual":146.0,"DT_RowId":"row_null"}],"DT_RowId":"row_null"}],"draw":null,"recordsTotal":5}';

            var d = JSON.parse(data);
            draw(d.raCounts);

            function draw(data){

                //svg
                var svg = d3.select("svg"),
                    margin = {top: 100, right: 80, bottom: 30, left: 50},
                    width = svg.attr("width") - margin.left - margin.right,
                    height = svg.attr("height") - margin.top - margin.bottom,
                    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");


                //time
                var parseTime = d3.timeParse("%Y%m%d");

                //domain
//              var x = d3.scaleTime().range([0, width]),
                var x = d3.scaleLinear().range([0, width]),
                    y = d3.scaleLinear().range([height, 0]),
                    z = d3.scaleOrdinal(d3.schemeCategory10);

                //line
                var line = d3.line()
                    .curve(d3.curveBasis)
                    .x(function(d) { 
                        return x(d.date_); })
                    .y(function(d) { 
                        return y(d.actual); });

                  //domain
                  x.domain(d3.extent(data[0].values, function(d) { 
                      return d.date_; }));

                  y.domain([
                    d3.min(data, function(c) { 
                        return d3.min(c.values, function(d) {
                            return d.actual; }); }),
                    d3.max(data, function(c) { 
                        return d3.max(c.values, function(d) {
                            return d.actual; }); })
                  ]);

                  z.domain(data.map(function(c) { 
                      return c.DT_RowId; }));

                  //axis
                  g.append("g")
                      .attr("class", "axis axis--x")
                      .attr("transform", "translate(0," + height + ")")
                      .call(d3.axisBottom(x));

                  g.append("g")
                      .attr("class", "axis axis--y")
                      .call(d3.axisLeft(y))
                    .append("text")
                      .attr("transform", "rotate(-90)")
                      .attr("y", 6)
                      .attr("dy", "0.71em")
                      .attr("fill", "#000")
                      .text("count");

                  var ra = g.selectAll(".ra")
                    .data(data)
                    .enter().append("g")
                      .attr("class", "ra");

                 //ra line
                  ra.append("path")
                      .attr("class", "line")
                      .attr("d",
                              function(d) { return 
                                  line(d.values); })
                      .style("stroke-dasharray", ("1","1"));
            }


            </script>
    </section>

</body>
</html>

Upvotes: 1

Views: 785

Answers (3)

altocumulus
altocumulus

Reputation: 21578

I think both Gerardo Furtado's answer as well as Luke Woodward's answer have good points, but both circumvent the fact, that OP's solution is somewhat off the beaten track. To make full use of the data binding the typical approach would be something like the following:

//ra line
ra.selectAll("path.line")
  .data(function(d) { return [d.values]; })
  .enter().append("path")
    .attr("class", "line")
    .attr("d", line)

Passing just the line generator function get rids of the automatical semicolon insertion after the return statement. On the other hand, doing the data binding for the path.line element still allows for multiple lines drawn by the same statement.

Have a look at the following snippet for a working example:

		var data =
		  '{"recordsFiltered":5,"raCounts":[{"name":"comp_name","values":[{"date_":"2016","actual":170.0,"DT_RowId":"row_null"},{"date_":"2015","actual":198.0,"DT_RowId":"row_null"},{"date_":"2015","actual":149.0,"DT_RowId":"row_null"},{"date_":"2014","actual":197.0,"DT_RowId":"row_null"},{"date_":"2014","actual":146.0,"DT_RowId":"row_null"}],"DT_RowId":"row_null"}],"draw":null,"recordsTotal":5}';

		data = JSON.parse(data).raCounts;


		//svg
		var svg = d3.select("svg"),
		  margin = {
		    top: 100,
		    right: 80,
		    bottom: 30,
		    left: 50
		  },
		  width = svg.attr("width") - margin.left - margin.right,
		  height = svg.attr("height") - margin.top - margin.bottom,
		  g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");


		//time
		var parseTime = d3.timeParse("%Y%m%d");

		//domain
		//				var x = d3.scaleTime().range([0, width]),
		var x = d3.scaleLinear().range([0, width]),
		  y = d3.scaleLinear().range([height, 0]),
		  z = d3.scaleOrdinal(d3.schemeCategory10);

		//line
		var line = d3.line()
		  .curve(d3.curveBasis)
		  .x(function(d) {
		    return x(d.date_);
		  })
		  .y(function(d) {
		    return y(d.actual);
		  });

		//domain
		x.domain(d3.extent(data[0].values, function(d) {
		  return d.date_;
		}));

		y.domain([
		  d3.min(data, function(c) {
		    return d3.min(c.values, function(d) {
		      return d.actual;
		    });
		  }),
		  d3.max(data, function(c) {
		    return d3.max(c.values, function(d) {
		      return d.actual;
		    });
		  })
		]);

		z.domain(data.map(function(c) {
		  return c.DT_RowId;
		}));

		//axis
		g.append("g")
		  .attr("class", "axis axis--x")
		  .attr("transform", "translate(0," + height + ")")
		  .call(d3.axisBottom(x));

		g.append("g")
		  .attr("class", "axis axis--y")
		  .call(d3.axisLeft(y))
		  .append("text")
		  .attr("transform", "rotate(-90)")
		  .attr("y", 6)
		  .attr("dy", "0.71em")
		  .attr("fill", "#000")
		  .text("count");

		var ra = g.selectAll(".ra")
		  .data(data)
		  .enter().append("g")
		  .attr("class", "ra");

		//ra line
		ra.selectAll("path.line")
      .data(function(d) { return [d.values]; })
      .enter().append("path")
		  .attr("class", "line")
		  .attr("d", line)
		  .style("stroke-dasharray", ("1", "1"));
<style> .axis--x path {
  display: none;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}

</style>
<script src="https://d3js.org/d3.v4.js"></script>
<svg width="430" height="250">
</svg>

Upvotes: 3

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

You're not passing the correct data to your line generator. It should be:

ra.append("path")
    .attr("class", "line")
    .attr("d", line(data[0].values))
    .style("stroke-dasharray", ("1", "1"));

Here is your updated fiddle: http://jsfiddle.net/67zs8ph7/

PS: this will plot just one line (see comment below)

Upvotes: 0

Luke Woodward
Luke Woodward

Reputation: 64959

JavaScript doesn't always require semicolons at the end of a line. It will automatically insert them in certain situations, and the place where you call your line function is one of them:

                  .attr("d",
                          function(d) { return 
                              line(d.values); })

The fix is therefore to remove the newline after return:

                  .attr("d",
                          function(d) { return line(d.values); })

Upvotes: 3

Related Questions