Skip to content
Advertisement

how to create a line in d3?

I have managed to create a line chart in d3 but now need to overlay a couple of horizontal lines and vertical lines. Here is what the chart looks like: enter image description here

Here is the code:

 <!DOCTYPE html>
    <meta charset="utf-8">
    <style>

    body {
      font: 14px sans-serif;
    }

    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      stroke-width: 1.5px;
      shape-rendering: crispEdges;
    }

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

    .dot {
      stroke: blue;
    }

    .grid .tick {
        stroke: lightgrey;
        opacity: 0.7;
    }
    </style>
    <body>
    <script src="https://d3js.org/d3.v3.js"></script>
    <script>
          var tests = <?php echo $tests; ?>;
          console.log("tests=" +JSON.stringify(tests));
          var events = <?php echo $events; ?>;
          console.log("events=" +JSON.stringify(events));

    var margin = {top: 50, right: 20, bottom: 60, left: 90},
        width = 900 - margin.left - margin.right,
        height = 400 - margin.top - margin.bottom;

    var x = d3.time.scale()
        .range([0, width]);

    var y = d3.scale.linear()
        .range([height, 0]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .ticks(d3.time.years,1)
        //makes the xAxis ticks a little longer than the xMinorAxis ticks
        .tickSize(10)
        .orient("bottom");

    var xMinorAxis = d3.svg.axis()
        .scale(x)
        .ticks(d3.time.months,1)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

    var line = d3.svg.line()
        .x(function(d) { return x(d.date); })
        .y(function(d) { return y(d.total_km); });

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // function for the y grid lines
    function make_y_axis() {
      return d3.svg.axis()
          .scale(y)
          .orient("left")
          .ticks(5) //somehow this makes the y-axis grid draw every other line, rather than every line
    }

    var data = [];
    function DataPoint(x,y) {
        this.date_time = x;
        this.total_km = y;
    }

    var lowerLimit;
    var upperLimit;
    function loadData() {
        for (i=1; i < tests.length; i++) {
            var test = tests[i];
            console.log("x="+test[0]+", y="+test[1]);
            data.push(new DataPoint(test[0],test[1]));
            lowerLimit = test[2];
            upperLimit = test[3];
        }
    }
    loadData();
    console.log("data1="+JSON.stringify(data));

    function processData(data) {
        data.forEach(function(d) {
            console.log("d.date_time="+d.date_time +", d.total_km="+d.total_km);
            d.date = new Date(d.date_time);
            console.log("d.date=" +d.date);
        });

        //using imported data to define extent of x and y domains
        x.domain(d3.extent(data, function(d) { return d.date; }));
        y.domain(d3.extent(data, function(d) { return d.total_km; }));

        // Draw the y Grid lines
        svg.append("g")            
            .attr("class", "grid")
            .call(make_y_axis()
                .tickSize(-width, 0, 0) //causes the line to be drawn the full width of the chart
                .tickFormat("")
            )

        //draw the data line
        svg.append("path")
            .datum(data)
            .attr("class", "line")
            .attr("d", line);

        //draw the upper limit
        var minDate = new Date(data[0].date_time);
        console.log("minDate="+minDate +", x(minDate)="+x(minDate));
        var maxDate = new Date(data[data.length-1].date_time);
        console.log("maxDate="+maxDate +", x(maxDate)="+x(maxDate));
        svg.append("line")
            .attr("class", "x")
            .style("stroke", "red")
            .style("stroke-dasharray", "3,3")
            .style("opacity", 0) 
            .attr("x1", x(minDate))
            .attr("y1", y(upperLimit))
            .attr("x2", x(maxDate))      
            .attr("y2", y(upperLimit));

    //creating a group(g) and will append a circle and 2 lines inside each group
    var g = svg.selectAll()
            .data(data).enter().append("g");

       //The markers on the line
         g.append("circle")
             //circle radius is increased
            .attr("r", 4.5)
            .attr("cx", function(d) { return x(d.date); })
            .attr("cy", function(d) { return y(d.total_km); });

    svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis)
          .selectAll(".tick text")
          .call(wrap, 35);

    svg.append("g")
        .attr("class","xMinorAxis")
        .attr("transform", "translate(0," + height + ")")
        .style({ 'stroke': 'Black', 'fill': 'none', 'stroke-width': '1px'})
        .call(xMinorAxis)
        .selectAll("text").remove();

    svg.append("text")      // text label for the x-axis
            .attr("x", width / 2 )
            .attr("y",  height + margin.bottom)
            .style("text-anchor", "middle")
            .text("Date");

    svg.append("text")      // text label for the y-axis
            .attr("y",30 - margin.left)
            .attr("x",50 - (height / 2))
            .attr("transform", "rotate(-90)")
            .style("text-anchor", "end")
            .style("font-size", "16px")
            .text("Tryglycerides (mg/dL)");

    svg.append("text")      // text label for chart Title
            .attr("x", width / 2 )
            .attr("y", 0 - (margin.top/2))
            .style("text-anchor", "middle")
            .style("font-size", "16px") 
            .style("text-decoration", "underline") 
            .text("Tryglyceride Levels");

    svg.append("g")
          .attr("class", "y axis")
          .call(yAxis)
  };
  processData(data);
</script>

I want to create horizontal line at 149 for the upper limit where you want the triglyceride levels to be below. I try to create that line in the “draw the upper limit” section. But no line is drawn.

Advertisement

Answer

Well I’m not real happy with this solution, but it works. Could not figure out why the svg.append(“line”) command failed to display a line, so I used the svg.append(“path”) command instead. I added the following code:

var data2 = [];
data2.push(new DataPoint(data[0].date_time,149));
data2.push(new DataPoint(data[data.length-1].date_time,149));
svg.append("path")
    .datum(data2)
    .attr("d", line)
    .style("stroke", "red")
    .style("stroke-dasharray", "3,3")

Then I modified the DataPoint code to this:

function DataPoint(x,y) {
    this.date_time = x;
    this.date = new Date(x);
    this.total_km = y;
}

Now the chart has a red dashed line representing the tryglyceride upper limit: enter image description here

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement