Reputation: 14462
I want to have the HighChart update the series by added the next data point to the chart so that the chart "plays". I have a data series that contains both an X an Y component. I would like for chart to be updated (say every second) with the next point in this series. I am using this in a VB.NET 4 site using DotNet.HighCharts API. I have followed along on several demos (such as this one) and all of these are using some randomly generated value. How can I get the chart to use an existing set of points? Here is a jsFiddle using the random function - http://jsfiddle.net/tQpNN/3/ I just do not know how to iterate through the passed in data series (if that is the way to do it) or to make DotNet.HighCharts iterate for me.
EDIT with some code:
Dim stfipsList4 = (From r In dt4.AsEnumerable() Select r("areaname")).Distinct().ToList()
Dim SeriesList4 As New List(Of Series)(stfipsList4.Count)
Dim seriesItem4(stfipsList4.Count) As Series
Dim xDate4 As DateTime
Dim fakeDate4 As String
Dim sX4 As Integer
sX4 = 1
For Each state In stfipsList4
Dim data As New Dictionary(Of DateTime, Decimal)
Dim stateVal As String = state.ToString
Dim recCount As Integer = dt4.Rows.Count - 1
Dim seriesPointCount As Integer = dt4.Compute("Count(population)", "areaname = '" + stateVal + "'")
Dim chartData As Object(,) = New Object(seriesPointCount - 1, 1) {}
Dim x As Integer = 0
For i As Integer = 0 To recCount
If dt4.Rows(i)("areaname").ToString = stateVal Then
fakeDate4 = "1/1/" + dt4.Rows(i)("periodyear").ToString
xDate3 = DateTime.Parse(fakeDate4)
chartData.SetValue(xDate4.Date, x, 0)
chartData.SetValue(dt4.Rows(i)("population"), x, 1)
x += 1
End If
Next
seriesItem4(sX4) = New Series With {
.Name = state.ToString, _
.Data = New Helpers.Data(chartData)
}
SeriesList4.Add(seriesItem3(sX4))
sX4 = sX4 + 1
Next
Dim iterateData As String = JsonSerializer.Serialize(New Helpers.Data(New Object() {seriesItem3(1).Data}))
Dim chart4 As Highcharts = New Highcharts("chart4").SetOptions(New Helpers.GlobalOptions() With { _
.[Global] = New [Global]() With { _
.UseUTC = False _
} _
}).InitChart(New Chart() With { _
.DefaultSeriesType = ChartTypes.Spline, _
.MarginRight = 10, _
.Events = New ChartEvents() With { _
.Load = "ChartEventsLoad" _
} _
}).SetTitle(New Title() With { _
.Text = "Live data" _
}).SetXAxis(New XAxis() With { _
.Type = AxisTypes.Datetime, _
.TickPixelInterval = 150 _
}).SetSeries(New Series() With { _
.Data = New Helpers.Data(New Object() {})
}) _
.AddJavascripVariable("counter", "0") _
.AddJavascripVariable("stockData", iterateData) _
.AddJavascripFunction("ChartEventsLoad", "// set up the updating of the chart each second" & vbCr & vbLf & _
" var series = this.series[0];" & vbCr & vbLf & _
" setInterval(function() {" & vbCr & vbLf & _
" var x = stockData[counter].key;" & vbCr & vbLf & _
" var y = stockData[counter].value;" & vbCr & vbLf & _
" series.addPoint([x, y], true, series.points.length > 10);" & vbCr & vbLf & _
" counter++;" & vbCr & vbLf & _
"}, 1000);")
This passes in my series of data (could be 1 or multiple different individual series). What I want to do is have the series points "play" by adding one point at a time (with scaling of the x-axis but I do not want to remove any points). This dummy version just adds a new random y-value at a given instant. I am not sure how to iterate over my existing data.
This does set the "stockData" javascript var to my data set. I am seeing errors in FireBug stating that
stockData[counter] is undefined
The var counter
is defined in the $(document).ready(function)
along with the stockdata
and chart4
chart. See http://jsfiddle.net/ZvYT6/ for what the DotNet.Highcharts API spits out.
The in-line javascript for the iteration looks like this:
function ChartEventsLoad(){
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = stockData[counter].key;
var y = stockData[counter].value;
series.addPoint([x, y], true, series.points.length > 10);
counter++;
}, 1000);
}
});
The part I am really unsure on is the stockData[counter]
key/value. What is this called in javascript? stockdata is a list of data that looks like:
var stockData = { data: [{ data: [[Date.parse('01/01/1900 00:00:00'), 530000],
....,
[Date.parse('01/01/2010 00:00:00'), 18801310]]
}]
};
EDIT v4: Okay, so now I am able to parse out my array of data using some nasty javascript.
Dim iterateData As String = JsonSerializer.Serialize(seriesItem3(1))
Dim chart4 As Highcharts = New Highcharts("chart4").SetOptions(New Helpers.GlobalOptions() With { _
.[Global] = New [Global]() With { _
.UseUTC = False _
} _
}).InitChart(New Chart() With { _
.DefaultSeriesType = ChartTypes.Spline, _
.MarginRight = 10, _
.Events = New ChartEvents() With { _
.Load = "ChartEventsLoad" _
} _
}).SetTitle(New Title() With { _
.Text = "Live data" _
}).SetXAxis(New XAxis() With { _
.Type = AxisTypes.Datetime, _
.TickPixelInterval = 150 _
}).SetSeries(New Series() With { _
.Data = New Helpers.Data(New Object() {})
}) _
.AddJavascripVariable("counter", "0") _
.AddJavascripVariable("stockData", iterateData.ToString) _
.AddJavascripFunction("ChartEventsLoad", "// set up the updating of the chart each second" & vbCr & vbLf & _
" var result = stockData.data;" & vbCr & vbLf & _
" var series = this.series[0];" & vbCr & vbLf & _
" setInterval(function() {" & vbCr & vbLf & _
" var p = String(result[counter]);" & vbCr & vbLf & _
" var splitp = p.split("","");" & vbCr & vbLf & _
" var x = splitp[0];" & vbCr & vbLf & _
" var y = splitp[1];" & vbCr & vbLf & _
" series.addPoint([x, y], true, false, true);" & vbCr & vbLf & _
" counter++;" & vbCr & vbLf & _
"}, 1000);")
ltrChart4.Text = chart4.ToHtmlString()
If I look at the x and y values in firebug I can see that these are the expected values. However, my chart just updates with times on the x-axis starting at ~1900 hours and adds a point every second (per the javascript function) but there is no y value. In addition the y-axis appears to start at -2.5 - none of the values I am using are less than 1000 let alone 0. I am so close...
Upvotes: 1
Views: 1325
Reputation: 14462
Finally got this working. This is my solution - probably not the most pretty but it works.
The important bit is to pass the iterated
the iterateData.ToString()
. From this point you can then loop over that and then split on each element. I added in a check to make sure the addition of the points stops once we reach the last point in the data set. To do still is to allow it to handle more than one series and "play" them both.
Dim stfipsList4 = (From r In dt4.AsEnumerable() Select r("areaname")).Distinct().ToList()
Dim SeriesList4 As New List(Of Series)(stfipsList4.Count)
Dim seriesItem4(stfipsList4.Count) As Series
Dim xDate4 As DateTime
Dim fakeDate4 As String
Dim sX4 As Integer
sX4 = 1
For Each state In stfipsList4
Dim data As New Dictionary(Of DateTime, Decimal)
Dim stateVal As String = state.ToString
Dim recCount As Integer = dt4.Rows.Count - 1
Dim seriesPointCount As Integer = dt4.Compute("Count(population)", "areaname = '" + stateVal + "'")
Dim chartData As Object(,) = New Object(seriesPointCount - 1, 1) {}
Dim x As Integer = 0
For i As Integer = 0 To recCount
If dt4.Rows(i)("areaname").ToString = stateVal Then
fakeDate4 = "1/1/" + dt4.Rows(i)("periodyear").ToString
xDate3 = DateTime.Parse(fakeDate4)
chartData.SetValue(xDate4.Date, x, 0)
chartData.SetValue(dt4.Rows(i)("population"), x, 1)
x += 1
End If
Next
seriesItem4(sX4) = New Series With {
.Name = state.ToString, _
.Data = New Helpers.Data(chartData)
}
SeriesList4.Add(seriesItem3(sX4))
sX4 = sX4 + 1
Next
Dim iterateData As String = JsonSerializer.Serialize(seriesItem3(1))
Dim chart4 As Highcharts = New Highcharts("chart4").SetOptions(New Helpers.GlobalOptions() With { _
.[Global] = New [Global]() With { _
.UseUTC = False _
} _
}).InitChart(New Chart() With { _
.DefaultSeriesType = ChartTypes.Column, _
.MarginRight = 10, _
.Events = New ChartEvents() With { _
.Load = "ChartEventsLoad" _
} _
}).SetTitle(New Title() With { _
.Text = "Live data" _
}).SetXAxis(New XAxis() With { _
.Type = AxisTypes.Datetime, _
.TickPixelInterval = 150 _
}).SetSeries(New Series() With { _
.Data = New Helpers.Data(New Object() {}), _
.Name = seriesItem3(1).Name
}) _
.AddJavascripVariable("iterated", iterateData.ToString) _
.AddJavascripFunction("ChartEventsLoad", "// set up the updating of the chart each second" & vbCr & vbLf & _
" var result = iterated.data;" & vbCr & vbLf & _
" var counter = 0;" & vbCr & vbLf & _
" var series = this.series[0];" & vbCr & vbLf & _
" var loopseries = function() {" & vbCr & vbLf & _
" if (counter <= result.length) {" & vbCr & vbLf & _
" var p = String(result[counter]);" & vbCr & vbLf & _
" var splitp = p.split("","");" & vbCr & vbLf & _
" var x = Number(splitp[0]);" & vbCr & vbLf & _
" var y = Number(splitp[1]);" & vbCr & vbLf & _
" series.addPoint([x, y], true, series.points.length > 10, true);" & vbCr & vbLf & _
" counter++;" & vbCr & vbLf & _
" } else {" & vbCr & vbLf & _
" clearInterval(loopseries);" & vbCr & vbLf & _
" }};" & vbCr & vbLf & _
" setInterval(loopseries, 100);")
ltrChart4.Text = chart4.ToHtmlString()
Upvotes: 2
Reputation: 724
You can see the demo for "Spline Update Each Second" at the sample project of the DotNet.Highchart project
Anyway, here is an example code how you can add point each second in your chart when you iterate your data:
Highcharts chart = new Highcharts("chart")
.SetOptions(new GlobalOptions { Global = new Global { UseUTC = false } })
.InitChart(new Chart
{
DefaultSeriesType = ChartTypes.Spline,
MarginRight = 10,
Events = new ChartEvents
{
Load = "ChartEventsLoad"
}
})
.SetTitle(new Title { Text = "Live data" })
.SetXAxis(new XAxis
{
Type = AxisTypes.Datetime,
TickPixelInterval = 150
})
.SetSeries(new Series
{
Name = "Live data",
Data = new Data(new[] { new Point { X = Tools.GetTotalMilliseconds(DateTime.Now), Y = 0 } })
})
.AddJavascripVariable("counter", "0")
.AddJavascripVariable("stockData", JsonSerializer.Serialize(ChartsData.StockData))
.AddJavascripFunction("ChartEventsLoad",
@"// set up the updating of the chart each second
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(); // current time
var y = stockData[counter];
series.addPoint([x, y], true, series.points.length > 10);
counter++;
}, 1000);");
Sorry for the C# code. I hope this is helpful and you can find good converter.
Upvotes: 1