ChartDirector 7.0 (ASP/COM/VB Edition)

Zooming and Scrolling Demonstration (2) (Windows)




This sample program demonstrates a general zoomable and scrollable chart. The followings are the key elements of this sample program:

The main source code listing of this sample program is included at the end of this section. The code consists of the following main parts:

Source Code Listing

[Windows Version (in Visual Basic)] vbdemo\frmZoomScrollDemo2.frm
Option Explicit Private cd As New ChartDirector.API ' XY data points for the chart Private dataX0() Private dataY0() Private dataX1() Private dataY1() Private dataX2() Private dataY2() ' The full x-axis and y-axis scales at no zooming. Private minX As Double Private maxX As Double Private minY As Double Private maxY As Double ' Internal variables to keep track of which navigation button is pushed Private activeNavigateButton As Long ' The index of the navigation buttons in the NavigatePB array Private Const upLeftPB = 0 Private Const upPB = 1 Private Const upRightPB = 2 Private Const LeftPB = 3 Private Const CenterPB = 4 Private Const RightPB = 5 Private Const downLeftPB = 6 Private Const downPB = 7 Private Const downRightPB = 8 ' Internal variables to keep track of dragging of the navigation window Private isDraggingNavigatePad As Boolean Private mouseDownXCoor As Double Private mouseDownYCoor As Double ' ' Initialize the form ' Private Sub Form_Load() ' Initially, set mouse usage to pointer mode Call PointerPB_Click ' Load the data Call loadData ' Can draw the chart now Call ChartViewer1.UpdateViewPort(True, True) End Sub ' ' Load the data ' Private Sub loadData() ' ' For simplicity, in this demo, we just use hard coded data. In a real application, ' the data probably read from a dynamic source such as a database. (See the ' ChartDirector documentation on "Using Data Sources with ChartDirector" if you need ' some sample code on how to read data from database to array variables.) ' dataX0 = Array(10, 15, 6, -12, 14, -8, 13, -3, 16, 12, 10.5, -7, 3, -10, -5, 2, 5) dataY0 = Array(130, 150, 80, 110, -110, -105, -130, -15, -170, 125, 125, 60, 25, 150, 150, 15, _ 120) dataX1 = Array(6, 7, -4, 3.5, 7, 8, -9, -10, -12, 11, 8, -3, -2, 8, 4, -15, 15) dataY1 = Array(65, -40, -40, 45, -70, -80, 80, 10, -100, 105, 60, 50, 20, 170, -25, 50, 75) dataX2 = Array(-10, -12, 11, 8, 6, 12, -4, 3.5, 7, 8, -9, 3, -13, 16, -7.5, -10, -15) dataY2 = Array(65, -80, -40, 45, -70, -80, 80, 90, -100, 105, 60, -75, -150, -40, 120, -50, _ -30) End Sub ' ' User clicks on the Pointer pushbutton ' Private Sub PointerPB_Click() ChartViewer1.MouseUsage = cvScrollOnDrag End Sub ' ' User clicks on the Zoom In pushbutton ' Private Sub ZoomInPB_Click() ChartViewer1.MouseUsage = cvZoomIn End Sub ' ' User clicks on the Zoom Out pushbutton ' Private Sub ZoomOutPB_Click() ChartViewer1.MouseUsage = cvZoomOut End Sub ' ' User presses on one of the navigation buttons ' Private Sub NavigatePB_MouseDown(Index As Integer, Button As Integer, Shift As Integer, _ X As Single, Y As Single) If Index = CenterPB Then ' Center button - center the view port at the origin (0, 0) Call scrollChartTo(ChartViewer1, 0.5 - ChartViewer1.ViewportWidth / 2, _ 0.5 - ChartViewer1.ViewportHeight / 2) Else ' Enable the timer to shift the view port once per 100ms until button is released activeNavigateButton = Index ButtonTimer.Enabled = True End If End Sub ' ' User releases the navigation button ' Private Sub NavigatePB_MouseUp(Index As Integer, Button As Integer, Shift As Integer, _ X As Single, Y As Single) ' Stop the button timer activeNavigateButton = -1 ButtonTimer.Enabled = False End Sub ' ' Navigation button timer - fires once per 100ms if navigation button is pressed ' Private Sub ButtonTimer_Timer() If activeNavigateButton <> -1 Then ' Get current view port position Dim vpLeft As Double Dim vpTop As Double vpLeft = ChartViewer1.ViewportLeft vpTop = ChartViewer1.ViewportTop ' Each tick scroll the chart by 5% in the button direction If activeNavigateButton = LeftPB Or activeNavigateButton = upLeftPB Or _ activeNavigateButton = downLeftPB Then vpLeft = vpLeft - ChartViewer1.ViewportWidth * 0.05 End If If activeNavigateButton = RightPB Or activeNavigateButton = upRightPB Or _ activeNavigateButton = downRightPB Then vpLeft = vpLeft + ChartViewer1.ViewportWidth * 0.05 End If If activeNavigateButton = upPB Or activeNavigateButton = upLeftPB Or _ activeNavigateButton = upRightPB Then vpTop = vpTop - ChartViewer1.ViewportHeight * 0.05 End If If activeNavigateButton = downPB Or activeNavigateButton = downLeftPB Or _ activeNavigateButton = downRightPB Then vpTop = vpTop + ChartViewer1.ViewportHeight * 0.05 End If ' Scroll to the new view port position Call scrollChartTo(ChartViewer1, vpLeft, vpTop) End If End Sub ' ' User moves zoom control slide bar ' Private Sub ZoomBar_Scroll() ' Remember the center point Dim centerX As Double, centerY As Double centerX = ChartViewer1.ViewportLeft + ChartViewer1.ViewportWidth / 2 centerY = ChartViewer1.ViewportTop + ChartViewer1.ViewportHeight / 2 ' Aspect ratio and zoom factor Dim aspectRatio As Double, zoomTo As Double aspectRatio = ChartViewer1.ViewportWidth / ChartViewer1.ViewportHeight zoomTo = CDbl(ZoomBar.value) / ZoomBar.Max ' Zoom while preserving aspect ratio ChartViewer1.ViewportWidth = zoomTo * IIf(aspectRatio > 1, aspectRatio, 1) ChartViewer1.ViewportHeight = zoomTo * IIf(aspectRatio > 1, 1, 1 / aspectRatio) ' Adjust ViewPortLeft and ViewPortTop to keep center point unchanged ChartViewer1.ViewportLeft = centerX - ChartViewer1.ViewportWidth / 2 ChartViewer1.ViewportTop = centerY - ChartViewer1.ViewportHeight / 2 ' Update the chart Call ChartViewer1.UpdateViewPort(True, False) End Sub ' ' User click on the navigate window ' Private Sub NavigateWindow_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then ' Save the mouse coordinates to keep track of how far the navigateWindow has been dragged. isDraggingNavigatePad = True mouseDownXCoor = X mouseDownYCoor = Y End If End Sub ' ' User drags the navigate window ' Private Sub NavigateWindow_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If isDraggingNavigatePad Then ' Is currently dragging - compute where is the navigateWindow being dragged to Dim newLabelLeft As Double, newLabelTop As Double newLabelLeft = NavigateWindow.Left + X - mouseDownXCoor newLabelTop = NavigateWindow.Top + Y - mouseDownYCoor ' Ensure the navigateWindow is within the navigatePad container Dim internalPadWidth As Long, internalPadHeight As Long internalPadWidth = NavigatePad.Width - ScaleX(2, vbPixels, ScaleMode) internalPadHeight = NavigatePad.height - ScaleY(2, vbPixels, ScaleMode) If newLabelLeft < 0 Then newLabelLeft = 0 ElseIf newLabelLeft > internalPadWidth - NavigateWindow.Width Then newLabelLeft = internalPadWidth - NavigateWindow.Width End If If newLabelTop < 0 Then newLabelTop = 0 ElseIf newLabelTop > internalPadHeight - NavigateWindow.height Then newLabelTop = internalPadHeight - NavigateWindow.height End If ' Update the navigateWindow position as it is being dragged NavigateWindow.Left = newLabelLeft NavigateWindow.Top = newLabelTop ' Update the view port to reflect the navigation window ChartViewer1.ViewportLeft = CDbl(NavigateWindow.Left) / internalPadWidth ChartViewer1.ViewportTop = CDbl(NavigateWindow.Top) / internalPadHeight Call ChartViewer1.UpdateViewPort(True, False) End If End Sub ' ' User release mouse button on the navigate window ' Private Sub NavigateWindow_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) isDraggingNavigatePad = False End Sub ' ' Utility to scroll the view port to the given position if necessary ' Private Sub scrollChartTo(viewer As ChartViewer, vpLeft As Double, vpTop As Double) ' Validate the parameters Call viewer.validateViewPort ' Update chart only if the view port has changed If vpLeft <> viewer.ViewportLeft Or vpTop <> viewer.ViewportTop Then viewer.ViewportLeft = vpLeft viewer.ViewportTop = vpTop Call viewer.UpdateViewPort(True, False) End If End Sub ' ' Mouse moves over ChartViewer ' Private Sub ChartViewer1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 0 Then ' Mouse is over chart with mouse button released (not dragging) ' Update image map if necessary Call updateImageMap(ChartViewer1) End If End Sub ' ' User clicks on a hot spot on the chart ' Private Sub ChartViewer1_ClickHotSpot(hotSpot As Collection, Button As Integer, Shift As Integer, _ X As Single, Y As Single) ' We show the pop up dialog only when the mouse action is not zoom in or zoom out If ChartViewer1.MouseUsage <> cvZoomIn And ChartViewer1.MouseUsage <> cvZoomOut Then 'In this demo, just list out the information provided by ChartDirector about hot spot ParamViewer.Display hotSpot End If End Sub ' ' The ViewPortChanged event handler. This event occurs when the user changes the ChartViewer ' view port by dragging scrolling, or by zoom in/out, or the ChartViewer.updateViewPort method ' is being called. ' Private Sub ChartViewer1_ViewPortChanged(needUpdateChart As Boolean, needUpdateImageMap As Boolean) If Not isDraggingNavigatePad Then ' Update the navigator window size and position to reflect the view port Dim internalPadWidth As Long, internalPadHeight As Long internalPadWidth = NavigatePad.Width - ScaleX(2, vbPixels, ScaleMode) internalPadHeight = NavigatePad.height - ScaleY(2, vbPixels, ScaleMode) NavigateWindow.Left = CInt(ChartViewer1.ViewportLeft * internalPadWidth) NavigateWindow.Top = CInt(ChartViewer1.ViewportTop * internalPadHeight) NavigateWindow.Width = Int(ChartViewer1.ViewportWidth * internalPadWidth) NavigateWindow.height = Int(ChartViewer1.ViewportHeight * internalPadHeight) End If ' Synchronize the zoom bar value with the view port width/height ZoomBar.value = Int(0.5 + IIf(ChartViewer1.ViewportWidth > ChartViewer1.ViewportHeight, _ ChartViewer1.ViewportHeight, ChartViewer1.ViewportWidth) * ZoomBar.Max) ' Update chart and image map if necessary If needUpdateChart Then Call drawChart(ChartViewer1) End If If needUpdateImageMap Then Call updateImageMap(ChartViewer1) End If End Sub ' ' Draw the chart ' Private Sub drawChart(viewer As ChartViewer) ' Create an XYChart object 500 x 480 pixels in size, with light blue (c0c0ff) as background ' color Dim c As XYChart Set c = cd.XYChart(500, 480, &HC0C0FF) ' Set the plotarea at (50, 40) and of size 400 x 400 pixels. Use light grey (c0c0c0) horizontal ' and vertical grid lines. Set 4 quadrant coloring, where the colors of the quadrants alternate ' between lighter and deeper grey (dddddd/eeeeee). Call c.setPlotArea(50, 40, 400, 400, -1, -1, -1, &HC0C0C0, &HC0C0C0).set4QBgColor(&HDDDDDD, _ &HEEEEEE, &HDDDDDD, &HEEEEEE, &H0) ' Enable clipping mode to clip the part of the data that is outside the plot area. Call c.setClipping ' Set 4 quadrant mode, with both x and y axes symetrical around the origin Call c.setAxisAtOrigin(cd.XYAxisAtOrigin, cd.XAxisSymmetric + cd.YAxisSymmetric) ' Add a legend box at (450, 40) (top right corner of the chart) with vertical layout and 8 pts ' Arial Bold font. Set the background color to semi-transparent grey (40dddddd). Dim legendBox As legendBox Set legendBox = c.addLegend(450, 40, True, "arialbd.ttf", 8) Call legendBox.setAlignment(cd.TopRight) Call legendBox.setBackground(&H40DDDDDD) ' Add titles to axes Call c.xAxis().setTitle("Alpha Index") Call c.yAxis().setTitle("Beta Index") ' Set axes line width to 2 pixels Call c.xAxis().setWidth(2) Call c.yAxis().setWidth(2) ' The default ChartDirector settings has a denser y-axis grid spacing and less-dense x-axis grid ' spacing. In this demo, we want the tick spacing to be symmetrical. We use around 40 pixels ' between major ticks and 20 pixels between minor ticks. Call c.xAxis().setTickDensity(40, 20) Call c.yAxis().setTickDensity(40, 20) ' ' In this example, we represent the data by scatter points. If you want to represent the data by ' somethings else (lines, bars, areas, floating boxes, etc), just modify the code below to use ' the layer type of your choice. ' ' Add scatter layer, using 11 pixels red (ff33333) X shape symbols Call c.addScatterLayer(dataX0, dataY0, "Group A", cd.Cross2Shape(), 11, &HFF3333) ' Add scatter layer, using 11 pixels green (33ff33) circle symbols Call c.addScatterLayer(dataX1, dataY1, "Group B", cd.CircleShape, 11, &H33FF33) ' Add scatter layer, using 11 pixels blue (3333ff) triangle symbols Call c.addScatterLayer(dataX2, dataY2, "Group C", cd.TriangleSymbol, 11, &H3333FF) If maxX = minX Then ' The axis scale has not yet been set up. This means this is the first time the chart is ' drawn and it is drawn with no zooming. We can use auto-scaling to determine the ' axis-scales, then remember them for future use. ' explicitly auto-scale axes so we can get the axis scales Call c.layout ' save the axis scales for future use minX = c.xAxis().getMinValue() maxX = c.xAxis().getMaxValue() minY = c.yAxis().getMinValue() maxY = c.yAxis().getMaxValue() Else ' Compute the zoomed-in axis scales using the overall axis scales and ViewPort size Dim xScaleMin As Double Dim xScaleMax As Double Dim yScaleMin As Double Dim yScaleMax As Double xScaleMin = minX + (maxX - minX) * ChartViewer1.ViewportLeft xScaleMax = minX + (maxX - minX) * (ChartViewer1.ViewportLeft + ChartViewer1.ViewportWidth) yScaleMin = maxY - (maxY - minY) * (ChartViewer1.ViewportTop + ChartViewer1.ViewportHeight) yScaleMax = maxY - (maxY - minY) * ChartViewer1.ViewportTop ' *** use the following formula if you are using a log scale axis *** ' xScaleMin = minX * ((maxX / minX) ^ ChartViewer1.ViewPortLeft) ' xScaleMax = minX * ((maxX / minX) ^ (ChartViewer1.ViewPortLeft + _ ' ChartViewer1.ViewPortWidth)) ' yScaleMin = maxY * ((minY / maxY) ^ (ChartViewer1.ViewPortTop + _ ' ChartViewer1.ViewPortHeight)) ' yScaleMax = maxY * ((minY / maxY) ^ ChartViewer1.ViewPortTop) ' Set the axis scales Call c.xAxis().setLinearScale(xScaleMin, xScaleMax) Call c.xAxis().setRounding(False, False) Call c.yAxis().setLinearScale(yScaleMin, yScaleMax) Call c.yAxis().setRounding(False, False) End If ' Set the chart image to the ChartViewer Set viewer.Chart = c End Sub ' ' Apply image map used on the chart if not already applied ' Private Sub updateImageMap(viewer As ChartViewer) If viewer.ImageMap = "" Then viewer.ImageMap = viewer.Chart.getHTMLImageMap("clickable", "", _ "title='[{dataSetName}] Alpha = {x}, Beta = {value}'") End If End Sub