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:
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: