D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
ssmaroju
Full window
Github gist
Line and Area with missing data. Time manipulations using moment.js
<!DOCTYPE html> <meta charset="utf-8"> <style> /* set the CSS */ body { font: 12px Arial;} path { stroke: steelblue; stroke-width: 2; fill: none; } .line { fill: none; stroke: steelblue; stroke-width: 1.0px; } .dot { fill: white; stroke: steelblue; stroke-width: 0.5px; } .area { fill: lightsteelblue; stroke: none; } .axis path, .axis line { fill: none; stroke: grey; stroke-width: 1; shape-rendering: crispEdges; } div.tooltip { position: absolute; text-align: center; width: 150px; height: 28px; padding: 2px; font: 12px sans-serif; background: lightsteelblue; border: 0px; border-radius: 8px; /* pointer-events: none; This line needs to be removed */ } </style> <body> <!-- load the d3.js library --> <script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script> <script type="text/javascript" src="moment.js"></script> <script type="text/javascript" src="moment-timezone.js"></script> <script> // Set the dimensions of the canvas / graph var margin = {top: 30, right: 20, bottom: 30, left: 50}, width = 600 - margin.left - margin.right, height = 270 - margin.top - margin.bottom; // Parse the date / time var parseDate = d3.time.format("%Y-%m-%d %X").parse; //27-May-12 16:00:00. This is used for D3JS parsing var formatTime = d3.time.format("%Y-%m-%d %X");// Format tooltip date / time // Set the ranges var x = d3.time.scale().range([0, width]); var y = d3.scale.linear().range([height, 0]); // Define the axes var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(5); var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(5); // Define the line var valueline = d3.svg.line() .defined(function (d) { return d; }) // This is important to define to identify nulls and break the line. .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.close); }); // Define the area for min/max var valuearea = d3.svg.area() .defined(function (d) { return d; }) // This is important to define to identify nulls and break the line. .x(function(d) { return x(d.date); }) .y1(function(d) { return y(d.max); }) .y0(function(d) { return y(d.min); }); // Define 'div' for tooltips var div = d3.select("body") .append("div") // declare the tooltip div .attr("class", "tooltip") .style("opacity", 0); // Adds the svg canvas 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 + ")"); // Get the data d3.csv("datatips.csv", function(error, data) { data.forEach(function(d) { d.dateUTC = parseDate(moment.utc(d.date).format("YYYY-MM-DD HH:mm:ss")); // using moment to get proper UTC time and formatting for D3 d.date = parseDate(moment.tz(moment.utc(d.date).clone(), "America/Chicago").format("YYYY-MM-DD HH:mm:ss"));// Converting UTC time to US/Chicago time and formatting for D3 parseDate d.close = +d.close; d.min = +d.min; d.max = +d.max; }); var dateRange = d3.extent(data, function(d) { return d.date; }); // Scale the range of the data x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { return d.max; })]); var startDate = moment(dateRange[0]); var endDate = moment(dateRange[1]); // Add the X Axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); // Add the Y Axis svg.append("g") .attr("class", "y axis") .call(yAxis); // Define a function that finds all possible date time values given the selected date time range and aggregate type. If timezone is already taken care of (ideally, it should be taken care before here), we can eliminate it here. function allDatesFun(startDate, endDate, timezone, aggType){ // I did not handle time series aggregate types. we need to know the sample rate for time series (for example 4 hz or 0.25 secs). This information needs parsing separately. var allDates = []; var intervalVal = Math.round(aggType.substr(0,aggType.length-1)); var intervalType = aggType.substr(-1).toLowerCase(); do { allDates.push({dateT: parseDate(moment.tz(moment(startDate._d), timezone).format("YYYY-MM-DD HH:mm:ss"))}); startDate = startDate.clone().add(intervalVal, intervalType); } while (startDate <= endDate); return allDates; } var allDates = allDatesFun(startDate, endDate, "America/Chicago", "1H"); function join(dataTable, allTable, dataTableKey, allTableKey, select) { var l = dataTable.length, m = allTable.length, lookupIndex = [], output = []; for (var i = 0; i < l; i++) { // loop through l items var row = dataTable[i]; lookupIndex[row[dataTableKey]] = row; // create an index for lookup table } for (var j = 0; j < m; j++) { // loop through m items var y = allTable[j]; var x = lookupIndex[y[allTableKey]]; // get corresponding row from lookupTable output.push(select(y, x)); // select only the columns you need } return output; } // here we are identifying gaps and marking the object null corresponding to missing data data = join(data, allDates, "date", "dateT", function(allDateObject, dataObject) { return (dataObject !== undefined)? dataObject: null; }); // Add the valuearea path. svg.append("path") .attr("class", "area") .attr("d", valuearea(data)); // Add the valueline path. svg.append("path") .attr("class", "line") .attr("d", valueline(data)); // draw the scatterplot svg.selectAll("dot") .data(data) .enter().append("circle") .filter(function(d) { return (d !== null) }) .attr("class", "dot") .attr("r", 2) .attr("cx", function(d) { return x(d.date); }) .attr("cy", function(d) { return y(d.close); }) // Tooltip stuff after this .on("mouseover", function(d) { div.transition() .duration(500) .style("opacity", 0); div.transition() .duration(200) .style("opacity", .9); div .html( '<a href= "'+d.link+'" target="_blank">' + //with a link formatTime(d.date) + "</a>" + "<br/>" + d.close) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }); }); </script> </body>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js