|
Add zoom to real time chart |
Posted by Hun Siong on Nov-19-2013 21:00 |
|
Dear Sir/Madam,
Please help.. Urgent.. I am having difficulty adding zoom feature to the real time directory chart. Below is my code. Please advise anything I have missed out. The zoom feature is totally not working.
Thank You.
Imports ChartDirector
Public Class FrmZoomScrollTrack2
' Data arrays
'Dim timeStamps As DateTime()
'Dim dataSeriesA As Double()
'Dim dataSeriesB As Double()
'Dim dataSeriesC As Double()
' The data arrays that store the visible data. The data arrays are updated in realtime. In
' this demo, we plot the last 240 samples.
Private Const sampleSize As Integer = 240
Private dataSeriesA(sampleSize - 1) As Double
Private dataSeriesB(sampleSize - 1) As Double
Private dataSeriesC(sampleSize - 1) As Double
Private timeStamps(sampleSize - 1) As Date
' The index of the array position to which new data values are added.
Private currentIndex As Integer = 0
' In this demo, we use a data generator driven by a timer to generate realtime data. The
' nextDataTime is an internal variable used by the data generator to keep track of which
' values to generate next.
Private nextDataTime As DateTime = New DateTime((Now.Ticks \\ 10000000) * 10000000)
' Flag to indicated if initialization has been completed. Prevents events from firing before
' controls are properly initialized.
Private hasFinishedInitialization As Boolean
Private Sub FrmZoomScrollTrack2_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles MyBase.Load
' Load the data
'loadData()
'' Initialize the WinChartViewer
'initChartViewer(winChartViewer1)
'' Can handle events now
'hasFinishedInitialization = True
'' Trigger the ViewPortChanged event to draw the chart
' Initialize the view port to show the latest 20% of the time range
winChartViewer1.setFullRange("x", 0, timeStamps.Length - 1)
' Initialize the view port to show the latest 250 points
winChartViewer1.ViewPortWidth = timeStamps.Length
winChartViewer1.ViewPortLeft = 1 - winChartViewer1.ViewPortWidth
'Set the maximum zoom to 10 points
winChartViewer1.ZoomInWidthLimit = 10 / timeStamps.Length
winChartViewer1.ZoomDirection = WinChartDirection.HorizontalVertical
' Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
' Data generation rate
dataRateTimer.Interval = 250
' Chart update rate
chartUpdateTimer.Interval = CInt(samplePeriod.Value)
' Initialize data buffer. In this demo, we just set the initial state to no data.
Dim i As Integer
For i = 0 To UBound(timeStamps)
timeStamps(i) = DateTime.MinValue
Next
' Set the maximum zoom to 10 points
'winChartViewer1.ZoomInWidthLimit = 10.0 / timeStamps.Length
' Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
pointerPB.Checked = True
' Enable RunPB button
runPB.Checked = True
' Now can start the timers for data collection and chart update
dataRateTimer.Start()
chartUpdateTimer.Start()
'winChartViewer1.updateViewPort(True, True)
End Sub
'
' Load the data
'
Private Sub loadData()
' In this example, we just use random numbers as data.
Dim r As RanSeries = New RanSeries(127)
timeStamps = r.getDateSeries(1827, New DateTime(2007, 1, 1), 86400)
dataSeriesA = r.getSeries2(1827, 150, -10, 10)
dataSeriesB = r.getSeries2(1827, 200, -10, 10)
dataSeriesC = r.getSeries2(1827, 250, -8, 8)
End Sub
'
' Initialize the WinChartViewer
'
Private Sub initChartViewer(ByVal viewer As WinChartViewer)
' Set the full x range to be the duration of the data
viewer.SetFullRange("x", timeStamps(0), timeStamps(timeStamps.Length - 1))
' Initialize the view port to show the latest 20% of the time range
viewer.ViewPortWidth = 0.2
viewer.ViewPortLeft = 1 - viewer.ViewPortWidth
' Set the maximum zoom to 10 points
viewer.ZoomInWidthLimit = 10.0 / timeStamps.Length
' Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
pointerPB.Checked = True
End Sub
'
' The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in
' or out the chart by dragging or clicking on the chart. It can also be triggered by
' calling WinChartViewer.updateViewPort.
'
Private Sub winChartViewer1_ViewPortChanged(ByVal sender As Object, _
ByVal e As WinViewPortEventArgs) Handles winChartViewer1.ViewPortChanged
' In addition to updating the chart, we may also need to update other controls that
' changes based on the view port.
'updateControls(winChartViewer1)
' Update the chart if necessary
If e.NeedUpdateChart Then
drawChart(winChartViewer1)
End If
' We need to update the track line too. If the mouse is moving on the chart (eg. if
' the user drags the mouse on the chart to scroll it), the track line will be updated
' in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
If (Not winChartViewer1.IsInMouseMoveEvent) And winChartViewer1.IsMouseOnPlotArea Then
trackLineLegend(winChartViewer1.Chart, winChartViewer1.PlotAreaMouseX)
winChartViewer1.updateDisplay()
End If
'drawChart(winChartViewer1)
End Sub
'
' Update controls when the view port changed
'
Private Sub updateControls(ByVal viewer As WinChartViewer)
' Update the start date and end date control to reflect the view port.
startDateCtrl.Value = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft))
endDateCtrl.Value = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft + _
viewer.ViewPortWidth))
' Update the scroll bar to reflect the view port position and width of the view port.
hScrollBar1.Enabled = winChartViewer1.ViewPortWidth < 1
hScrollBar1.LargeChange = Math.Ceiling(winChartViewer1.ViewPortWidth * _
(hScrollBar1.Maximum - hScrollBar1.Minimum))
hScrollBar1.SmallChange = Math.Ceiling(hScrollBar1.LargeChange * 0.1)
hScrollBar1.Value = Math.Round(winChartViewer1.ViewPortLeft * _
(hScrollBar1.Maximum - hScrollBar1.Minimum)) + hScrollBar1.Minimum
End Sub
'
' Draw the chart and display it in the given viewer.
'
Private Sub drawChart(ByVal viewer As WinChartViewer)
' Create an XYChart object 600 x 270 pixels in size, with light grey (f4f4f4)
' background, black (000000) border, 1 pixel raised effect, and with a rounded frame.
Dim c As XYChart = New XYChart(640, 350, &HF4F4F4, &H0, 1)
c.setRoundedFrame(Chart.CColor(BackColor))
' Set the plotarea at (55, 55) and of size 520 x 185 pixels. Use white (ffffff)
' background. Enable both horizontal and vertical grids by setting their colors to
' grey (cccccc). Set clipping mode to clip the data lines to the plot area.
c.setPlotArea(55, 55, 520, 185, &HFFFFFF, -1, -1, &HCCCCCC, &HCCCCCC)
c.setClipping()
' Add a title to the chart using 15 pts Times New Roman Bold Italic font, with a light
' grey (dddddd) background, black (000000) border, and a glass like raised effect.
c.addTitle("Field Intensity at Observation Satellite", "Times New Roman Bold Italic", 15 _
).setBackground(&HDDDDDD, &H0, Chart.glassEffect())
' Set the reference font size of the legend box
c.getLegend().setFontSize(8)
' Configure the y-axis with a 10pts Arial Bold axis title
c.yAxis().setTitle("Intensity (V/m)", "Arial Bold", 10)
' Configure the x-axis to auto-scale with at least 75 pixels between major tick and 15
' pixels between minor ticks. This shows more minor grid lines on the chart.
c.xAxis().setTickDensity(75, 15)
' Set the axes width to 2 pixels
c.xAxis().setWidth(2)
c.yAxis().setWidth(2)
' Now we add the data to the chart
Dim firstTime As DateTime = timeStamps(0)
If firstTime <> DateTime.MinValue Then
'
' Set up the x-axis scale. In this demo, we set the x-axis to show the 240 samples,
' with 250ms per sample.
c.xAxis().setDateScale(firstTime, firstTime.AddSeconds( _
dataRateTimer.Interval * timeStamps.Length / 1000))
' Set the x-axis label format
c.xAxis().setLabelFormat("{value|hh:nn:ss}")
' Create a line layer to plot the lines
Dim layer As LineLayer = c.addLineLayer2()
layer.setFastLineMode()
' The x-coordinates are the timeStamps.
layer.setXData(timeStamps)
' The 3 data series are used to draw 3 lines.
layer.addDataSet(dataSeriesA, &HFF0000, "Alpha")
layer.addDataSet(dataSeriesB, &HCC00, "Beta")
layer.addDataSet(dataSeriesC, &HFF, "Gamma")
End If
' Include track line with legend. If the mouse is on the plot area, show the track
' line with legend at the mouse position; otherwise, show them for the latest data
' values (that is, at the rightmost position).
trackLineLegend(c, IIf(viewer.IsMouseOnPlotArea, viewer.PlotAreaMouseX, _
c.getPlotArea().getRightX()))
'viewer.syncLinearAxisWithViewPort("x", c.xAxis())
'viewer.syncLinearAxisWithViewPort("y", c.yAxis())
'viewer.syncDateAxisWithViewPort("x", c.xAxis())
' Assign the chart to the WinChartViewer
viewer.Chart = c
End Sub
''
'' Draw the chart.
''
'Private Sub drawChart(ByVal viewer As WinChartViewer)
' ' Get the start date and end date that are visible on the chart.
' Dim viewPortStartDate As DateTime = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft))
' Dim viewPortEndDate As DateTime = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft + _
' viewer.ViewPortWidth))
' ' Get the array indexes that corresponds to the visible start and end dates
' Dim startIndex As Integer = Math.Floor(Chart.bSearch(timeStamps, viewPortStartDate))
' Dim endIndex As Integer = Math.Ceiling(Chart.bSearch(timeStamps, viewPortEndDate))
' Dim noOfPoints As Integer = endIndex - startIndex + 1
' ' Extract the part of the data array that are visible.
' Dim viewPortTimeStamps As DateTime() = Chart.arraySlice(timeStamps, startIndex, noOfPoints)
' Dim viewPortDataSeriesA As Double() = Chart.arraySlice(dataSeriesA, startIndex, noOfPoints)
' Dim viewPortDataSeriesB As Double() = Chart.arraySlice(dataSeriesB, startIndex, noOfPoints)
' Dim viewPortDataSeriesC As Double() = Chart.arraySlice(dataSeriesC, startIndex, noOfPoints)
' '
' ' At this stage, we have extracted the visible data. We can use those data to plot the chart.
' '
' '================================================================================
' ' Configure overall chart appearance.
' '================================================================================
' ' Create an XYChart object of size 640 x 350 pixels
' Dim c As XYChart = New XYChart(640, 350)
' ' Set the plotarea at (55, 50) with width 80 pixels less than chart width, and height 85 pixels
' ' less than chart height. Use a vertical gradient from light blue (f0f6ff) to sky blue (a0c0ff)
' ' as background. Set border to transparent and grid lines to white (ffffff).
' c.setPlotArea(55, 50, c.getWidth() - 80, c.getHeight() - 85, c.linearGradientColor(0, 50, 0, _
' c.getHeight() - 35, &HF0F6FF, &HA0C0FF), -1, Chart.Transparent, &HFFFFFF, &HFFFFFF)
' ' As the data can lie outside the plotarea in a zoomed chart, we need enable clipping.
' c.setClipping()
' ' Add a title to the chart using 18 pts Times New Roman Bold Italic font
' c.addTitle(" Zooming and Scrolling with Track Line (2)", "Times New Roman Bold Italic", 18)
' ' Add a legend box at (55, 25) using horizontal layout. Use 8pts Arial Bold as font. Set the
' ' background and border color to Transparent and use line style legend key.
' Dim b As LegendBox = c.addLegend(55, 25, False, "Arial Bold", 8)
' b.setBackground(Chart.Transparent)
' b.setLineStyleKey()
' ' Set the axis stem to transparent
' c.xAxis().setColors(Chart.Transparent)
' c.yAxis().setColors(Chart.Transparent)
' ' Add axis title using 10pts Arial Bold Italic font
' c.yAxis().setTitle("Ionic Temperature (C)", "Arial Bold Italic", 10)
' '================================================================================
' ' Add data to chart
' '================================================================================
' '
' ' In this example, we represent the data by lines. You may modify the code below to use other
' ' representations (areas, scatter plot, etc).
' '
' ' Add a line layer for the lines, using a line width of 2 pixels
' Dim layer As LineLayer = c.addLineLayer2()
' Layer.setLineWidth(2)
' ' In this demo, we do not have too many data points. In real code, the chart may contain a lot
' ' of data points when fully zoomed out - much more than the number of horizontal pixels in this
' ' plot area. So it is a good idea to use fast line mode.
' Layer.setFastLineMode()
' ' Now we add the 3 data series to a line layer, using the color red (ff33333), green (008800)
' ' and blue (3333cc)
' Layer.setXData(viewPortTimeStamps)
' ' Layer.addDataSet(viewPortDataSeriesA, &HFF3333, "Alpha")
' ' Layer.addDataSet(viewPortDataSeriesB, &H008800, "Beta")
' ' layer.addDataSet(viewPortDataSeriesC, &H3333CC, "Gamma")
' ' The 3 data series are used to draw 3 lines.
' layer.addDataSet(dataSeriesA, &HFF0000, "Alpha")
' layer.addDataSet(dataSeriesB, &HCC00, "Beta")
' layer.addDataSet(dataSeriesC, &HFF, "Gamma")
' '================================================================================
' ' Configure axis scale and labelling
' '================================================================================
' ' Set the x-axis as a date/time axis with the scale according to the view port x range.
' viewer.SyncDateAxisWithViewPort("x", c.xAxis())
' '
' ' In this demo, the time range can be from a few years to a few days. We demonstrate how to set
' ' up different date/time format based on the time range.
' '
' ' If all ticks are yearly aligned, then we use "yyyy" as the label format.
' c.xAxis().setFormatCondition("align", 360 * 86400)
' c.xAxis().setLabelFormat("{value|yyyy}")
' ' If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first label of a
' ' year, and "mmm" for other labels.
' c.xAxis().setFormatCondition("align", 30 * 86400)
' c.xAxis().setMultiFormat(Chart.StartOfYearFilter(), "<*font=bold*>{value|mmm yyyy}", _
' Chart.AllPassFilter(), "{value|mmm}")
' ' If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the first
' ' label of a year, and "mmm dd" in bold font as the first label of a month, and "dd" for other
' ' labels.
' c.xAxis().setFormatCondition("align", 86400)
' c.xAxis().setMultiFormat(Chart.StartOfYearFilter(), _
' "<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", Chart.StartOfMonthFilter(), _
' "<*font=bold*>{value|mmm dd}")
' c.xAxis().setMultiFormat2(Chart.AllPassFilter(), "{value|dd}")
' ' For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
' ' and "hh:nn" for other labels.
' c.xAxis().setFormatCondition("else")
' c.xAxis().setMultiFormat(Chart.StartOfDayFilter(), "<*font=bold*>{value|hh:nn<*br*>mmm dd}", _
' Chart.AllPassFilter(), "{value|hh:nn}")
' '================================================================================
' ' Output the chart
' '================================================================================
' viewer.Chart = c
'End Sub
'
' Pointer (Drag to Scroll) button event handler
'
Private Sub pointerPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles pointerPB.CheckedChanged
If sender.Checked Then
winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag
End If
End Sub
'
' Zoom In button event handler
'
Private Sub zoomInPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles zoomInPB.CheckedChanged
If sender.Checked Then
winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn
End If
End Sub
'
' Zoom Out button event handler
'
Private Sub zoomOutPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles zoomOutPB.CheckedChanged
If sender.Checked Then
winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut
End If
End Sub
'
' The scroll bar event handler
'
Private Sub hScrollBar1_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles hScrollBar1.ValueChanged
' When the view port is changed (user drags on the chart to scroll), the scroll bar will get
' updated. When the scroll bar changes (eg. user drags on the scroll bar), the view port will
' get updated. This creates an infinite loop. To avoid this, the scroll bar can update the
' view port only if the view port is not updating the scroll bar.
If hasFinishedInitialization And Not winChartViewer1.IsInViewPortChangedEvent Then
' Set the view port based on the scroll bar
winChartViewer1.ViewPortLeft = (hScrollBar1.Value - hScrollBar1.Minimum) / _
(hScrollBar1.Maximum - hScrollBar1.Minimum)
' Trigger a view port changed event to update the chart
winChartViewer1.updateViewPort(True, False)
End If
End Sub
'
' Start Date control event handler
'
Private Sub startDateCtrl_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles startDateCtrl.ValueChanged
' The date control can update the view port only if it is not currently being updated in the
' view port changed event (that is, only if the date is changed due to user action).
If hasFinishedInitialization And Not winChartViewer1.IsInViewPortChangedEvent Then
' The updated view port width
Dim vpWidth As Double = winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth - _
winChartViewer1.GetViewPortAtValue("x", Chart.CTime(startDateCtrl.Value))
' Make sure the updated view port width is within bounds
vpWidth = Math.Max(winChartViewer1.ZoomInWidthLimit, Math.Min(vpWidth, _
winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth))
' Update view port and trigger a view port changed event to update the chart
winChartViewer1.ViewPortLeft += winChartViewer1.ViewPortWidth - vpWidth
winChartViewer1.ViewPortWidth = vpWidth
winChartViewer1.updateViewPort(True, False)
End If
End Sub
'
' End Date control event handler
'
Private Sub endDateCtrl_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles endDateCtrl.ValueChanged
' The date control can update the view port only if it is not currently being updated in the
' view port changed event (that is, only if the date is changed due to user action).
If hasFinishedInitialization And Not winChartViewer1.IsInViewPortChangedEvent Then
' The updated view port width
Dim vpWidth As Double = winChartViewer1.GetViewPortAtValue("x", _
Chart.CTime(endDateCtrl.Value)) - winChartViewer1.ViewPortLeft
' Make sure the updated view port width is within bounds
vpWidth = Math.Max(winChartViewer1.ZoomInWidthLimit, Math.Min(vpWidth, _
1 - winChartViewer1.ViewPortLeft))
' Update view port and trigger a view port changed event to update the chart
winChartViewer1.ViewPortWidth = vpWidth
winChartViewer1.updateViewPort(True, False)
End If
End Sub
'
' We want to use the mouse wheel for zoom in/out when the mouse is over the chart. To to do, we need
' to set the WinChartViewer to be the "active control" when the mouse enters the chart.
'
' Variable to save the original active control
Private activeControlSave As Control = Nothing
'
' Mouse Enter event handler
'
Private Sub winChartViewer1_MouseEnter(ByVal sender As Object, ByVal e As EventArgs) _
Handles winChartViewer1.MouseEnter
' Save the original active control and set the WinChartViewer to be the active control, so that
' the WinChartViewer can receive the mouse wheel event.
activeControlSave = winChartViewer1.FindForm().ActiveControl
winChartViewer1.FindForm().ActiveControl = winChartViewer1
End Sub
'
' Mouse Leave event handler
'
Private Sub winChartViewer1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) _
Handles winChartViewer1.MouseLeave
' Restore the original active control.
winChartViewer1.FindForm().ActiveControl = activeControlSave
End Sub
'
' Mouse Wheel event handler
'
Private Sub winChartViewer1_MouseWheel(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseWheel
' We zoom in or out by 10% depending on the mouse wheel direction.
Dim rx As Double = IIf(e.Delta > 0, 0.9, 1 / 0.9)
Dim ry As Double = rx
' We do not zoom in beyond the zoom in width or height limit.
rx = Math.Max(rx, winChartViewer1.ZoomInWidthLimit / winChartViewer1.ViewPortWidth)
ry = Math.Max(ry, winChartViewer1.ZoomInWidthLimit / winChartViewer1.ViewPortHeight)
If rx = 1 And ry = 1 Then
Return
End If
Dim c As XYChart = winChartViewer1.Chart
'
' Set the view port position and size so that it is zoom in/out around the mouse by the
' desired ratio.
'
Dim mouseOffset As Double = (winChartViewer1.ChartMouseX - c.getPlotArea().getLeftX()) / _
c.getPlotArea().getWidth()
winChartViewer1.ViewPortLeft += mouseOffset * (1 - rx) * winChartViewer1.ViewPortWidth
winChartViewer1.ViewPortWidth *= rx
Dim mouseOffsetY As Double = (winChartViewer1.ChartMouseY - c.getPlotArea().getTopY()) / _
c.getPlotArea().getHeight()
winChartViewer1.ViewPortTop += mouseOffsetY * (1 - ry) * winChartViewer1.ViewPortHeight
winChartViewer1.ViewPortHeight *= ry
' Trigger a view port changed event to update the chart
winChartViewer1.updateViewPort(True, False)
End Sub
''
'' Mouse Wheel event handler
''
'Private Sub winChartViewer1_MouseWheel(ByVal sender As Object, _
' ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseWheel
' ' We zoom in or out by 10% depending on the mouse wheel direction.
' Dim r As Double = IIf(e.Delta > 0, 0.9, 1 / 0.9)
' ' We do not zoom in beyond the zoom in width limit.
' If ((r = Math.Max(r, winChartViewer1.ZoomInWidthLimit / winChartViewer1.ViewPortWidth)) = 1) Then
' Return
' End If
' Dim c As XYChart = winChartViewer1.Chart
' ' Set the view port position and size so that it is zoom in/out around the mouse by the
' ' desired ratio.
' Dim mouseOffset As Double = (e.X - c.getPlotArea().getLeftX()) / c.getPlotArea().getWidth()
' winChartViewer1.ViewPortLeft += mouseOffset * (1 - r) * winChartViewer1.ViewPortWidth
' winChartViewer1.ViewPortWidth *= r
' ' Trigger a view port changed event to update the chart
' winChartViewer1.updateViewPort(True, False)
'End Sub
'
' Draw track cursor when mouse is moving over plotarea
'
Private Sub winChartViewer1_MouseMovePlotArea(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseMovePlotArea
'Dim viewer As WinChartViewer = sender
'trackLineLabel(viewer.Chart, viewer.PlotAreaMouseX)
'viewer.updateDisplay()
'' Hide the track cursor when the mouse leaves the plot area
'viewer.removeDynamicLayer("MouseLeavePlotArea")
Dim viewer As WinChartViewer = sender
trackLineLegend(viewer.Chart, viewer.PlotAreaMouseX)
viewer.updateDisplay()
End Sub
'
' Draw track line with data labels
'
Private Sub trackLineLabel(ByVal c As XYChart, ByVal mouseX As Integer)
' Clear the current dynamic layer and get the DrawArea object to draw on it.
Dim d As DrawArea = c.initDynamicLayer()
' The plot area object
Dim plotArea As PlotArea = c.getPlotArea()
' Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
Dim xValue As Double = c.getNearestXValue(mouseX)
Dim xCoor As Integer = c.getXCoor(xValue)
' Draw a vertical track line at the x-position
d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(&H0, &H101))
' Draw a label on the x-axis to show the track line position.
Dim xlabel As String = "<*font,bgColor=000000*> " & c.xAxis().getFormattedLabel(xValue, _
"mmm dd, yyyy") & " <*/font*>"
Dim t As TTFText = d.text(xlabel, "Arial Bold", 8)
' Restrict the x-pixel position of the label to make sure it stays inside the chart image.
Dim xLabelPos As Integer = Math.Max(0, Math.Min(xCoor - t.getWidth() / 2, c.getWidth() - t.getWidth( _
)))
t.draw(xLabelPos, plotArea.getBottomY() + 6, &HFFFFFF)
' Iterate through all layers to draw the data labels
For i As Integer = 0 To c.getLayerCount() - 1
Dim layer As Layer = c.getLayerByZ(i)
' The data array index of the x-value
Dim xIndex As Integer = layer.getXIndexOf(xValue)
' Iterate through all the data sets in the layer
For j As Integer = 0 To layer.getDataSetCount() - 1
Dim dataSet As ChartDirector.DataSet = layer.getDataSetByZ(j)
' Get the color and position of the data label
Dim color As Integer = dataSet.getDataColor()
Dim yCoor As Integer = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis())
' Draw a track dot with a label next to it for visible data points in the plot area
If (yCoor >= plotArea.getTopY()) And (yCoor <= plotArea.getBottomY()) And (color <> _
Chart.Transparent) And (Not String.IsNullOrEmpty(dataSet.getDataName())) Then
d.circle(xCoor, yCoor, 4, 4, color, color)
Dim label As String = "<*font,bgColor=" & Hex(color) & "*> " & c.formatValue( _
dataSet.getValue(xIndex), "{value|P4}") & " <*/font*>"
t = d.text(label, "Arial Bold", 8)
' Draw the label on the right side of the dot if the mouse is on the left side the chart,
' and vice versa. This ensures the label will not go outside the chart image.
If xCoor <= (plotArea.getLeftX() + plotArea.getRightX()) / 2 Then
t.draw(xCoor + 5, yCoor, &HFFFFFF, Chart.Left)
Else
t.draw(xCoor - 5, yCoor, &HFFFFFF, Chart.Right)
End If
End If
Next
Next
End Sub
Private Sub chartUpdateTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chartUpdateTimer.Tick
winChartViewer1.updateViewPort(True, False)
End Sub
Private Sub dataRateTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dataRateTimer.Tick
Do While nextDataTime < DateTime.Now
'
' In this demo, we use some formulas to generate new values. In real applications,
' it may be replaced by some data acquisition code.
'
Dim p As Double = nextDataTime.Ticks / 10000000.0 * 4
Dim dataA As Double = 20 + Math.Cos(p * 2.2) * 10 + 1 / (Math.Cos(p) * Math.Cos(p) + 0.01)
Dim dataB As Double = 150 + 100 * Math.Sin(p / 27.7) * Math.Sin(p / 10.1)
Dim dataC As Double = 150 + 100 * Math.Cos(p / 6.7) * Math.Cos(p / 11.9)
' We provide some visual feedback to the numbers generated, so you can see the
' values being generated.
valueA.Text = dataA.ToString(".##")
valueB.Text = dataB.ToString(".##")
valueC.Text = dataC.ToString(".##")
' After obtaining the new values, we need to update the data arrays.
If currentIndex < timeStamps.Length Then
' Store the new values in the current index position, and increment the index.
dataSeriesA(currentIndex) = dataA
dataSeriesB(currentIndex) = dataB
dataSeriesC(currentIndex) = dataC
timeStamps(currentIndex) = nextDataTime
currentIndex += 1
Else
' The data arrays are full. Shift the arrays and store the values at the end.
shiftData(dataSeriesA, dataA)
shiftData(dataSeriesB, dataB)
shiftData(dataSeriesC, dataC)
shiftData(timeStamps, nextDataTime)
End If
' Update nextDataTime. This is needed by our data generator. In real applications,
' you may not need this variable or the associated do/while loop.
nextDataTime = nextDataTime.AddMilliseconds(dataRateTimer.Interval)
Loop
winChartViewer1.updateViewPort(True, False)
End Sub
'
' Utility to shift a value into an array
'
Private Sub shiftData(ByVal data As Object, ByVal newValue As Object)
Dim i As Integer
For i = 1 To UBound(data)
data(i - 1) = data(i)
Next
data(UBound(data)) = newValue
End Sub
'
' Draw the track line with legend
'
Private Sub trackLineLegend(ByVal c As XYChart, ByVal mouseX As Integer)
' Clear the current dynamic layer and get the DrawArea object to draw on it.
Dim d As DrawArea = c.initDynamicLayer()
' The plot area object
Dim plotArea As PlotArea = c.getPlotArea()
' Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
Dim xValue As Double = c.getNearestXValue(mouseX)
Dim xCoor As Integer = c.getXCoor(xValue)
' Draw a vertical track line at the x-position
d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(&H0, &H101))
' Container to hold the legend entries
Dim legendEntries As ArrayList = New ArrayList()
' Iterate through all layers to build the legend array
For i As Integer = 0 To c.getLayerCount() - 1
Dim layer As Layer = c.getLayerByZ(i)
' The data array index of the x-value
Dim xIndex As Integer = layer.getXIndexOf(xValue)
' Iterate through all the data sets in the layer
For j As Integer = 0 To layer.getDataSetCount() - 1
Dim dataSet As ChartDirector.DataSet = layer.getDataSetByZ(j)
' We are only interested in visible data sets with names
Dim dataName As String = dataSet.getDataName()
Dim color As Integer = dataSet.getDataColor()
If (Not String.IsNullOrEmpty(dataName)) And (color <> Chart.Transparent) Then
' Build the legend entry, consist of the legend icon, name and data value.
Dim dataValue As Double = dataSet.getValue(xIndex)
legendEntries.Add("<*block*>" & dataSet.getLegendIcon() & " " & dataName & ": " & IIf( _
dataValue = Chart.NoValue, "N/A", c.formatValue(dataValue, "{value|P4}")) & "<*/*>")
' Draw a track dot for data points within the plot area
Dim yCoor As Integer = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis())
If (yCoor >= plotArea.getTopY()) And (yCoor <= plotArea.getBottomY()) Then
d.circle(xCoor, yCoor, 4, 4, color, color)
End If
End If
Next
Next
' Create the legend by joining the legend entries
legendEntries.Reverse()
Dim legendText As String = "<*block,maxWidth=" & plotArea.getWidth() & _
"*><*block*><*font=Arial Bold*>[" & c.xAxis().getFormattedLabel(xValue, "hh:nn:ss.ff") & _
"]<*/*> " & Join(CType(legendEntries.ToArray(GetType(String)), String()), " ") & _
"<*/*>"
' Display the legend on the top of the plot area
Dim t As TTFText = d.text(legendText, "Arial", 8)
t.draw(plotArea.getLeftX() + 5, plotArea.getTopY() - 3, &H0, Chart.BottomLeft)
End Sub
Private Sub freezePB_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles freezePB.CheckedChanged
chartUpdateTimer.Enabled = runPB.Checked
End Sub
End Class |
Re: Add zoom to real time chart |
Posted by Hun Siong on Nov-19-2013 21:03 |
|
Dear Sir/Madam,
I am using zooming and scrolling with track line sample and integrate with the real time track line. But having issue on the zooming issue.
Please help.
Hun Siong |
Re: Add zoom to real time chart |
Posted by Hun Siong on Nov-20-2013 20:23 |
|
Hi Peter,
Please help me. Urgent.
Thank You.
Best Regards,
Hun Siong |
Re: Add zoom to real time chart |
Posted by Peter Kwan on Nov-21-2013 03:30 |
|
Hi Hun Siong,
There are many ways to add realtime chart features to a zoomable and scrollable chart. I happend to have an example written in C++/MFC. I have just ported it to VB as attached.
Hope this can help.
Regards
Peter Kwan
|
Re: Add zoom to real time chart |
Posted by Hun Siong on Nov-22-2013 11:13 |
|
Dear Peter,
It works. Thanks a lot.
Best Regards,
Hun Siong |
Re: Add zoom to real time chart |
Posted by Arumugam on Mar-23-2015 16:31 |
|
Hi Peter,
Can you give same sample code for C# also with zoom & pan in all direction support.
Thanks. |
|