I did have one notable issue with previous charts being cached and showing through when I would mouse over certain data points. Luckily this was a fairly well known issue and there was a simple solution, using the destroy() method.
chart.destroy();
I am still working on a few more controls, I've provided controls for entering specific start times and selecting the number of samples to display:
var start = document.getElementById("tbTime").value;
As you can see this is still a work in progress. Next thing I want to work on is a listview to select multiple data streams from the given table, connecting to (ftp) online data sources and updating my database automatically (differential updates) so I can collect data from different sources online. This may take me a while to complete (what with coding full time at work) but that's the plan.
You can see the completed code below:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@{ | |
ViewBag.Title = "Plot"; | |
} | |
<h3>Time Based Plot </h3> | |
<div> | |
<cpanel class="plotControls"> | |
<input class="btn btn-default" id="btnGetData" type="button" value="Plot" /> | |
<label for="tbTime" class="plotControls">Time Start</label> | |
<input class="tb" type="text" name="time" id="tbTime" /> | |
<label for="tbSpan" class="plotControls">Num Samples</label> | |
<input class="tb" type="text" name="samples" id="tbSamples" /> | |
<label for="tbId">Record Id</label> | |
<input class="tb" type="text" name="recordId" id="tbId" /> | |
@*.DropDownListFor(p => p.SelectedCountryID, | |
Model.CountryIEnum, | |
"Select property", | |
new | |
{ | |
@id = "Country-DropdownID", | |
@class = "Country-DropdownCls" | |
})*@ | |
</cpanel> | |
</div> | |
<canvas class="plot" id="myChart" width="900" height="400"></canvas> | |
<script> | |
$(document).ready(function () { | |
$('#btnGetData').click(function () { | |
var urlString = getUrl(); | |
$.ajax({ | |
type: 'GET', | |
url: urlString, | |
success: function (data) { | |
plotFunction(data); | |
}, | |
dataType: "json" | |
}); | |
}); | |
}); | |
// create url for my web api route | |
function getUrl() | |
{ | |
var idStr = document.getElementById("tbId").value; | |
var start = document.getElementById("tbTime").value; | |
var samples = document.getElementById("tbSamples").value; | |
var urlString = urlString = "@ViewData["serviceUrl"]" + "//api" + "//temp" + "//get"; | |
if (!isBlank(idStr)) { | |
urlString += '//' + idStr; | |
console.log(urlString); | |
} else if (!isBlank(start) & !isBlank(samples)) { | |
urlString += '//' + start.toString() + '//' + samples.toString(); | |
console.log(urlString); | |
} | |
return urlString; | |
} | |
function isBlank(str) { | |
return (!str || /^\s*$/.test(str)); | |
} | |
var propName = "TempC"; | |
var myLineChart = null; | |
function plotFunction(jsonObj) { | |
// clear old data/chart | |
if (myLineChart != null) { | |
myLineChart.destroy(); | |
} | |
var ctx = document.getElementById("myChart").getContext("2d"); | |
var tempData = jsonObj.Data.Data; | |
// select data by property name | |
var toPlot = tempData.map(function (v) { | |
return v[propName]; | |
}); | |
var x = tempData.map(function (v) { | |
return v.DateTime; | |
}); | |
var options = Chart.defaults.global = { | |
// Boolean - Whether to animate the chart | |
animation: true, | |
// Number - Number of animation steps | |
animationSteps: 60, | |
// String - Animation easing effect | |
animationEasing: "easeOutQuart", | |
// Boolean - If we should show the scale at all | |
showScale: true, | |
// Boolean - If we want to override with a hard coded scale | |
scaleOverride: false, | |
// ** Required if scaleOverride is true ** | |
// Number - The number of steps in a hard coded scale | |
scaleSteps: null, | |
// Number - The value jump in the hard coded scale | |
scaleStepWidth: null, | |
// Number - The scale starting value | |
scaleStartValue: null, | |
// String - Colour of the scale line | |
scaleLineColor: "rgba(0,0,0,.1)", | |
// Number - Pixel width of the scale line | |
scaleLineWidth: 1, | |
// Boolean - Whether to show labels on the scale | |
scaleShowLabels: true, | |
// Interpolated JS string - can access value | |
scaleLabel: "<%=value%>", | |
// Boolean - Whether the scale should stick to integers, not floats even if drawing space is there | |
scaleIntegersOnly: true, | |
// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value | |
scaleBeginAtZero: false, | |
// String - Scale label font declaration for the scale label | |
scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", | |
// Number - Scale label font size in pixels | |
scaleFontSize: 12, | |
// String - Scale label font weight style | |
scaleFontStyle: "normal", | |
// String - Scale label font colour | |
scaleFontColor: "#666", | |
// Boolean - whether or not the chart should be responsive. | |
responsive: true, | |
// Boolean - whether to maintain the starting aspect ratio or not when responsive | |
maintainAspectRatio: true, | |
// Boolean - Determines whether to draw tooltips on the canvas or not | |
showTooltips: true, | |
// Function - Determines whether to execute the customTooltips function instead | |
customTooltips: false, | |
// Array - Array of string names to attach tooltip events | |
tooltipEvents: ["mousemove", "touchstart", "touchmove"], | |
// String - Tooltip background colour | |
tooltipFillColor: "rgba(0,0,0,0.8)", | |
// String - Tooltip label font declaration for the scale label | |
tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", | |
// Number - Tooltip label font size in pixels | |
tooltipFontSize: 14, | |
// String - Tooltip font weight style | |
tooltipFontStyle: "normal", | |
// String - Tooltip label font colour | |
tooltipFontColor: "#fff", | |
// String - Tooltip title font declaration for the scale label | |
tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", | |
// Number - Tooltip title font size in pixels | |
tooltipTitleFontSize: 14, | |
// String - Tooltip title font weight style | |
tooltipTitleFontStyle: "bold", | |
// String - Tooltip title font colour | |
tooltipTitleFontColor: "#fff", | |
// Number - pixel width of padding around tooltip text | |
tooltipYPadding: 6, | |
// Number - pixel width of padding around tooltip text | |
tooltipXPadding: 6, | |
// Number - Size of the caret on the tooltip | |
tooltipCaretSize: 8, | |
// Number - Pixel radius of the tooltip border | |
tooltipCornerRadius: 6, | |
// Number - Pixel offset from point x to tooltip edge | |
tooltipXOffset: 10, | |
// String - Template string for single tooltips | |
tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>", | |
// String - Template string for multiple tooltips | |
multiTooltipTemplate: "<%= value %>", | |
// Function - Will fire on animation progression. | |
onAnimationProgress: function () { }, | |
// Function - Will fire on animation completion. | |
onAnimationComplete: function () { }, | |
///Boolean - Whether grid lines are shown across the chart | |
scaleShowGridLines: true, | |
//String - Colour of the grid lines | |
scaleGridLineColor: "rgba(0,0,0,.05)", | |
//Number - Width of the grid lines | |
scaleGridLineWidth: 1, | |
//Boolean - Whether to show horizontal lines (except X axis) | |
scaleShowHorizontalLines: true, | |
//Boolean - Whether to show vertical lines (except Y axis) | |
scaleShowVerticalLines: true, | |
//Boolean - Whether the line is curved between points | |
bezierCurve: true, | |
//Number - Tension of the bezier curve between points | |
bezierCurveTension: 0.4, | |
//Boolean - Whether to show a dot for each point | |
pointDot: false, | |
//Number - Radius of each point dot in pixels | |
pointDotRadius: 4, | |
//Number - Pixel width of point dot stroke | |
pointDotStrokeWidth: 1, | |
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point | |
pointHitDetectionRadius: 4, | |
//Boolean - Whether to show a stroke for datasets | |
datasetStroke: true, | |
//Number - Pixel width of dataset stroke | |
datasetStrokeWidth: 2, | |
//Boolean - Whether to fill the dataset with a colour | |
datasetFill: true, | |
//String - A legend template | |
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>" | |
}; | |
var data = { | |
labels: x, | |
datasets: [ | |
{ | |
label: "Temperature (C)", | |
fillColor: "rgba(220,220,220,0.2)", | |
strokeColor: "rgba(220,220,220,1)", | |
pointColor: "rgba(220,220,220,1)", | |
pointStrokeColor: "#fff", | |
pointHighlightFill: "#fff", | |
pointHighlightStroke: "rgba(220,220,220,1)", | |
data: toPlot | |
} | |
] | |
}; | |
myLineChart = new Chart(ctx).Line(data, options); | |
}; | |
</script> |
![]() |
Simple time-based plot |
So far I have the ftp request method running:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void FtpRequest(string ftpPath, string destPath) | |
{ | |
// Get the object used to communicate with the server. | |
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpPath); | |
request.Method = WebRequestMethods.Ftp.DownloadFile; | |
// This example assumes the FTP site uses anonymous logon. | |
request.Credentials = new NetworkCredential(userName, passWord); | |
FtpWebResponse response = (FtpWebResponse)request.GetResponse(); | |
Stream responseStream = response.GetResponseStream(); | |
StreamReader reader = new StreamReader(responseStream); | |
try | |
{ | |
WriteResponseToFile(destPath, response, responseStream); | |
} | |
catch (Exception ex) | |
{ | |
log.Debug(ex); | |
} | |
reader.Close(); | |
responseStream.Close(); | |
response.Close(); | |
} |