Platforms to show: All Mac Windows Linux Cross-Platform

/ChartDirector/ChartDirector Control for Web


Required plugins for this example: MBS Main Plugin, MBS ChartDirector Plugin, MBS Images Plugin

You find this example project in your Plugins Download as a Xojo project file within the examples folder: /ChartDirector/ChartDirector Control for Web

This example is the version from Mon, 2nd May 2021.

Project "ChartDirector Control for Web.xojo_binary_project"
Class App Inherits WebApplication
End Class
Class Session Inherits WebSession
Const ErrorDialogCancel = "Do Not Send"
Const ErrorDialogMessage = "This application has encountered an error and cannot continue."
Const ErrorDialogQuestion = "Please describe what you were doing right before the error occurred:"
Const ErrorDialogSubmit = "Send"
Const ErrorThankYou = "Thank You"
Const ErrorThankYouMessage = "Your feedback helps us make improvements."
Const NoJavascriptInstructions = "To turn Javascript on, please refer to your browser settings window."
Const NoJavascriptMessage = "Javascript must be enabled to access this page."
End Class
Class WebPage1 Inherits WebPage
Control a11 Inherits ChartDirectorControl
ControlInstance a11 Inherits ChartDirectorControl
EventHandler Sub Open() // create test data Dim x0 As Double = 70 Dim x1 As Double = 50 Dim x2 As Double = 30 Data0.Append(x0) Data1.Append(x1) Data2.Append(x2) // Create randomized data points for line chart demo For I As Integer = 1 To 100 x0 = x0 + Rnd() * 5.0 - 2.5 x1 = x1 + Rnd() * 5.0 - 2.5 x2 = x2 + Rnd() * 5.0 - 2.5 Data0.Append(x0) Data1.Append(x1) Data2.Append(x2) Next Dim P As Picture // Ghost the overlay image P = GetMBSLogo(200) P.Mask.Graphics.ForeColor = &cDDDDDD P.Mask.Graphics.FillRect(0, 0, P.Width, P.Height) // Set the overlay image Me.OverlayPicture = P End EventHandler
EventHandler Function Render(Factor As Double, Width As Integer, Height As Integer) As CDBaseChartMBS CDBaseChartMBS.ScaleFactor = 2 // let plugin do double Resolution // The data for the line chart comes from properties // Create a XYChart object of size 600 x 375 pixels dim c as new CDXYChartMBS(width*factor, height*factor) 'C.setBackground(C.kTransparent) C.setTransparentColor(-1) C.setClipping(0) C.setAntiAlias(True, C.kAntiAlias) // Add a title to the chart using 18 pts Times Bold Italic font call c.addTitle("Product Line Global Revenue", "timesbi.ttf", 18) // Set the plotarea at (50, 55) and of 500 x 280 pixels in size. Use a vertical // gradient color from light blue (f9f9ff) to sky blue (aaccff) as background. // Set border to transparent and grid lines to white (ffffff). call c.setPlotArea(50*factor, 55*factor, (width-100)*factor, (height-100)*factor, c.linearGradientColor(0, 55, 0, 335, &hf9fcff, &haaccff), -1, c.kTransparent, &hffffff) call c.setClipping // Add a legend box at (50, 28) using horizontal layout. Use 10pts Arial Bold as // font, with transparent background. c.addLegend(50*factor, 28*factor, false, "arialbd.ttf", 10*factor).setBackground(c.kTransparent) // Set the x axis labels 'call c.xAxis.setLabels(labels) // Set y-axis tick density to 30 pixels. ChartDirector auto-scaling will use this // as the guideline when putting ticks on the y-axis. c.yAxis.setTickDensity(30*factor) c.yAxis2.setTickDensity(30*factor) // Set axis label style to 8pts Arial Bold call c.xAxis.setLabelStyle("arialbd.ttf", 8*factor) call c.yAxis.setLabelStyle("arialbd.ttf", 8*factor) call c.yAxis2.setLabelStyle("arialbd.ttf", 8*factor) // Set axis line width to 2 pixels c.xAxis.setWidth(2*factor) c.yAxis.setWidth(2*factor) c.yAxis2.setWidth(2*factor) // Add axis title using 10pts Arial Bold Italic font call c.yAxis.setTitle("Revenue in US millions", "arialbi.ttf", 10*factor) call c.yAxis2.setTitle("Revenue in US millions", "arialbi.ttf", 10*factor) // scroll c.xAxis.setLinearScale(0.0, 100.0) c.xAxis.setRounding(false, false) c.yAxis.setLinearScale(0.0, 100.0) c.yAxis.setRounding(false, false) c.yAxis2.setLinearScale(0.0, 100.0) c.yAxis2.setRounding(false, false) // Add a line layer to the chart dim layer as CDLineLayerMBS layer = c.addLineLayer // Set the line width to 3 pixels layer.setLineWidth(3) // Add the three data sets to the line layer, using circles, diamands and X // shapes as symbols dim d as CDDataSetMBS d=layer.addDataSet(data0, &hff0000, "Quantum Computer") d.setDataSymbol(c.kCircleSymbol, 9*factor) d.setLineWidth(factor) d=layer.addDataSet(data1, &h00ff00, "Atom Synthesizer") d.setDataSymbol(c.kDiamondSymbol, 11*factor) d.setLineWidth(factor) d=layer.addDataSet(data2, &hff6600, "Proton Cannon") d.setLineWidth(factor) d.setDataSymbol(c.Cross2Shape, 11*factor) Return c End EventHandler
End Control
Control aa21 Inherits ChartDirectorControl
ControlInstance aa21 Inherits ChartDirectorControl
EventHandler Function Render(Factor As Double, Width As Integer, Height As Integer) As CDBaseChartMBS CDBaseChartMBS.ScaleFactor = 2 // let plugin do double Resolution dim f as double = factor // scale factor, 1 for screen and 4 or more for printing dim data0(-1) as double = array(6, 12.5, 18.2, 15.0) dim angles0(-1) as double = array(45, 96, 169, 258.0) dim size0(-1) as double = array(f*41, f*105, f*12, f*20.0) dim data1(-1) as double = array(18, 16, 11, 14.0) dim angles1(-1) as double = array(30, 210, 240, 310.0) dim size1(-1) as double = array(f*30, f*45, f*12, f*90.0) // Create a PolarChart object of size 460 x 460 pixels dim c as new CDPolarChartMBS(f*width, f*height) // Add a title to the chart at the top left corner using 15pts Arial Bold Italic // font call c.addTitle(CDPolarChartMBS.kTopLeft, "<*underline=2*>EM Field Strength", "arialbi.ttf", f*15) // Set center of plot area at (230, 240) with radius 180 pixels c.setPlotArea(f*width/2, f*height/2, f*min(width,height)*0.35) // Use alternative light grey/dark grey circular background color c.setPlotAreaBg(&hdddddd, &heeeeee) // Set the grid style to circular grid c.setGridStyle(false) // Add a legend box at the top right corner of the chart using 9 pts Arial Bold // font c.addLegend(f*width-f*2, f*0, true, "arialbd.ttf", f*9).setAlignment(CDPolarChartMBS.kTopRight) // Set angular axis as 0 - 360, with a spoke every 30 units c.angularAxis.setLinearScale(0, 360, 30) c.radialAxis.setLinearScale 0, 20,5 // Set the radial axis label format c.radialAxis.setLabelFormat("{value} km") c.angularAxis.setLabelGap f*8 call c.angularAxis.setLabelStyle "",8*f call c.radialAxis.setLabelStyle "",8*f // Add a blue (&h9999ff) line layer to the chart using (data0, angle0) dim layer0 as CDPolarLineLayerMBS layer0 = c.addLineLayer(data0, &h9999ff, "Cold Spot") layer0.setAngles(angles0) // Disable the line by setting its width to 0, so only the symbols are visible layer0.setLineWidth(0) // Use a circular data point symbol layer0.setDataSymbol(CDPolarChartMBS.kCircleSymbol, f*11) // Modulate the symbol size by size0 to produce a bubble chart effect layer0.setSymbolScale(size0) // Add a red (&hff9999) line layer to the chart using (data1, angle1) dim layer1 as CDPolarLineLayerMBS layer1 = c.addLineLayer(data1,&hff9999, "Hot Spot") layer1.setAngles(angles1) // Disable the line by setting its width to 0, so only the symbols are visible layer1.setLineWidth(0) // Use a circular data point symbol layer1.setDataSymbol(CDPolarChartMBS.kCircleSymbol, f*11) // Modulate the symbol size by size1 to produce a bubble chart effect layer1.setSymbolScale(size1) // Output the chart Return c End EventHandler
End Control
Control a31 Inherits ChartDirectorControl
ControlInstance a31 Inherits ChartDirectorControl
EventHandler Sub ItemClicked(XLabel As String, X As Integer, DataSet As Integer, DataSetName As String, Value As Double, Title As String, Sector As Integer, Label As String) // Manage UI interaction with chart rendering variables If (Sector = HighLightSector) Then HighLightSector = -1 Else HighLightSector = Sector End If Me.Redraw End EventHandler
EventHandler Sub Open() Dim P As Picture // Ghost the overlay image P = GetMBSLogo(200) P.Mask.Graphics.ForeColor = &cDDDDDD P.Mask.Graphics.FillRect(0, 0, P.Width, P.Height) // Set the overlay image Me.OverlayPicture = P End EventHandler
EventHandler Function Render(Factor As Double, Width As Integer, Height As Integer) As CDBaseChartMBS CDBaseChartMBS.ScaleFactor = 2 // let plugin do double Resolution dim f as double = factor // scale factor, 1 for screen and 4 or more for printing // The data for the pie chart dim data(-1) as double = array(21.0, 18, 15, 12, 8, 24) // The labels for the pie chart dim labels(-1) as string = array("Labor", "Licenses", "Taxes", "Legal", "Facilities", "Production") // The colors to use for the sectors dim colors(-1) as integer colors.Append &h66aaee colors.Append &heebb22 colors.Append &hbbbbbb colors.Append &h8844ff colors.Append &hdd2222 colors.Append &h009900 // Create a PieChart object of size 600 x 320 pixels. Use a vertical gradient // color from light blue (99ccff) to white (ffffff) spanning the top 100 pixels // as background. Set border to grey (888888). Use rounded corners. Enable soft // drop shadow. dim c as new CDPieChartMBS(f*width, f*height) c.setBackground(c.linearGradientColor(0, 0, 0, 100, &h99ccff, &hffffff),&h888888) c.setRoundedFrame(&hFFFFFF,10*f) 'c.setDropShadow if HighLightSector>=0 then c.setExplode(HighLightSector) end if // Add a title using 18 pts Times New Roman Bold Italic font. Add 16 pixels top // margin to the title. c.addTitle("Pie Chart With Legend Demonstration", "timesbi.ttf", f*18).setMargin(0, 0, f*16, 0) // Set the center of the pie at (160, 165) and the radius to 110 pixels c.setPieSize(f*width/4, f*height/2, f*110) // Draw the pie in 3D with a pie thickness of 25 pixels c.set3D(f*25) // Set the pie data and the pie labels c.setData(data, labels) dim x as CDTextBoxMBS = c.setLabelStyle // Set the sector colors c.setColors(CDPieChartMBS.kDataColor, colors) // Use local gradient shading for the sectors 'c.setSectorStyle(CDPieChartMBS.kLocalGradientShading) // Use the side label layout method, with the labels positioned 16 pixels from // the pie bounding box c.setLabelLayout(CDPieChartMBS.kSideLayout, 16) // Show only the sector number as the sector label c.setLabelFormat("{={sector}+1}") c.setJoinLine 0,f // Set the sector label style to Arial Bold 10pt, with a dark grey (444444) // border dim t as CDTextBoxMBS=c.setLabelStyle("arialbd.ttf", f*10) t.setBackground(CDPieChartMBS.kTransparent, &h444444) // Add a legend box, with the center of the left side anchored at (330, 175), and // using 10 pts Arial Bold Italic font dim b as CDLegendBoxMBS = c.addLegend(f*width/2, f*height/2, true, "arialbi.ttf", f*10) b.setAlignment(CDPieChartMBS.kLeft) // Set the legend box border to dark grey (444444), and with rounded conerns b.setBackground(CDPieChartMBS.kTransparent, &h444444) b.setRoundedCorners(f*10) // Set the legend box margin to 16 pixels, and the extra line spacing between the // legend entries as 5 pixels b.setMargin(f*16) b.setKeySpacing(0, 5*f) // Set the legend box icon to have no border (border color same as fill color) b.setKeyBorder(CDPieChartMBS.kSameAsMainColor) // Set the legend text to show the sector number, followed by a 120 pixels wide // block showing the sector label, and a 40 pixels wide block showing the // percentage // *2 as we have HiDPI! b.setText("<*block,valign=top*>{={sector}+1}.<*advanceTo="+str(f*22*2)+"*><*block,width="+str(f*120*2)+"*>{label}<*/*><*block,width="+str(f*40*2)+",halign=right*>{percent}<*/*>%") // Output the chart return c End EventHandler
End Control
Control a41 Inherits ChartDirectorControl
ControlInstance a41 Inherits ChartDirectorControl
EventHandler Function Render(Factor As Double, Width As Integer, Height As Integer) As CDBaseChartMBS CDBaseChartMBS.ScaleFactor = 2 // let plugin do double Resolution dim f as double = factor // scale factor, 1 for screen and 4 or more for printing // The data for the pyramid chart dim data(-1) as double = array(156.0, 123, 211, 179) // The labels for the pyramid chart dim labels(-1) as string = array("Funds", "Bonds", "Stocks", "Cash") // The semi-transparent colors for the pyramid layers dim colors(-1) as integer colors.Append &h60000088 colors.Append &h6066aaee colors.Append &h60ffbb00 colors.Append &h60ee6622 // Create a PyramidChart object of size 480 x 400 pixels dim c as new CDPyramidChartMBS(f*width, f*height) // Set the cone center at (280, 180), and width x height to 150 x 300 pixels c.setConeSize(f*width/2, f*height/2, f*min(height,width)*0.333, f*height*0.75) // Set the elevation to 15 degrees c.setViewAngle(15) // Set the pyramid data and labels c.setData(data, labels) // Set the layer colors to the given colors c.setColors(c.kDataColor, colors) // Leave 1% gaps between layers c.setLayerGap(0.01) c.setJoinLine(&h000000, f) // Add labels at the left side of the pyramid layers using Arial Bold font. The // labels will have 3 lines showing the layer name, value and percentage. call c.setLeftLabel("{label}"+EndOfLine.unix+"US ${value}K"+EndOfLine.unix+"({percent}%)", "arialbd.ttf",8*f) Return c End EventHandler
End Control
Control Label1 Inherits WebLabel
ControlInstance Label1 Inherits WebLabel
End Control
Function GetMBSLogo(w as integer) As Picture dim p as Picture = LogoMBS(500) dim q as new Picture(w,w,32) q.Graphics.DrawPicture p,0,0,w,w,0,0,500,500 Return q End Function
Property Protected Data0() As Double
Property Protected Data1() As Double
Property Protected Data2() As Double
Property Private HighLightSector As Integer
End Class
Class ChartDirectorControl Inherits WebImageView
Event ItemClicked(XLabel As String, X As Integer, DataSet As Integer, DataSetName As String, Value As Double, Title As String, Sector As Integer, Label As String) End Event
Event Open() End Event
Event Render(Factor As Double, Width As Integer, Height As Integer) As CDBaseChartMBS End Event
EventHandler Sub MouseDown(X As Integer, Y As Integer, Details As REALbasic.MouseEvent) Dim HotSpotID As Integer // Check if over a hotspot; Nil check prevents spurious NilObjectExceptions If (ImageMapHandler <> Nil) Then HotSpotID = ImageMapHandler.getHotSpot(X, Y) If (HotSpotID > 0) Then // Click SendClickEvent if ShowValueOnClick then DrawItemInfo(X, Y) end if End If End EventHandler
EventHandler Sub MouseExit() // Finalize redraw CleanUp End EventHandler
EventHandler Sub Open() // Call overridden superclass method Open Redraw End EventHandler
EventHandler Sub Resized() redraw End EventHandler
Private Sub CleanUp() // Finalize redraw If (NeedClear = True) Then NeedClear = False self.Picture = LastWebPicture End If End Sub
Function CurrentPicture() As Picture // Return the currently displayed chart image Return (LastPicture) End Function
Private Sub DrawItemInfo(X As Integer, Y As Integer) Dim Index as integer Dim Key, KeyValue As String Dim XLabel As String Dim XValue As String Dim DataSet As String Dim DataSetName As String Dim Value As String Dim Title As String Dim Sector As String Dim Label As String // Error check If (ImageMapHandler = Nil) Then Return // Do key/value pair priming calls Index = 0 Key = ImageMapHandler.getKey(Index) KeyValue = ImageMapHandler.getValue(Index) Do // NOTE: This is not the complete supported list of parameters; Refer to ChartDirector documentation on 'Parameter Substitution and Formatting' for additional parameters Select Case Key Case "xlabel" XLabel = KeyValue Case "x" XValue = KeyValue Case "dataset" DataSet = KeyValue Case "datasetname" DataSetName = KeyValue Case "value" Value = KeyValue Case "title" Title = KeyValue Case "sector" Sector = KeyValue Case "label" Label = KeyValue End Select Index = Index + 1 // Get next key/value pair Key = ImageMapHandler.getKey(Index) KeyValue = ImageMapHandler.getValue(Index) Loop Until Key.Len = 0 // Compose label graphic If (Label <> "") Then Value = Label + ": " + Value Dim B As Picture = New Picture(LastPicture.Width, LastPicture.Height) dim f as integer = 2 B.VerticalResolution = LastPicture.VerticalResolution b.HorizontalResolution = LastPicture.HorizontalResolution Dim G As Graphics = B.Graphics g.TextSize = 12 * f Dim W As Integer = 6 + G.StringWidth(Value) / f Dim H As Integer = 20 // Add some space between the cursor position and the initial label drawing position X = X + 10 Y = Y + 10 // If we are too close to the right, we need to move our label drawing position left If (X + W > G.Width) Then X = X - 20 - W // If we are too close to the bottom, we need to move our label drawing position up If (Y + H > G.Height) Then Y = Y - 20 - H // Draw in the current composited chart image B.Graphics.DrawPicture(LastPicture, 0, 0) if LastPicture.Mask <> nil and b.mask <> nil then B.Mask.Graphics.DrawPicture(LastPicture.Mask, 0, 0) end if // Draw the label graphic G.ForeColor = &cCCCC00 G.FillRect(X*f, Y*f, W*f, H*f) G.ForeColor = &c000000 G.DrawString(Value, f*(X + 3), f*(Y + 15)) // Update the composited chart image self.Picture = B NeedClear = True End Sub
Sub Redraw() // Trigger chart rendering (actual chart configuration and data plotting) Current = Render(1.0, me.Width, me.Height) If Current = Nil Then // If there is no valid chart object returned, clear the drawing region LastPicture = nil LastWebPicture = nil self.Picture = nil Else // Get the chart image based on the returned chart object LastPicture = Current.makeChartPicture // Support overlay picture drawing If (OverlayPicture <> Nil) Then LastPicture.Graphics.DrawPicture(OverlayPicture, (me.Width - OverlayPicture.Width) / 2, (me.Height - OverlayPicture.Height) / 2) End If // Support control border drawing If (Border = True) Then LastPicture.Graphics.PenHeight = 1 LastPicture.Graphics.PenWidth = 1 LastPicture.Graphics.ForeColor = &c000000 LastPicture.Graphics.DrawRect(0, 0, me.Width, me.Height) LastPicture.Mask.Graphics.PenHeight = 1 LastPicture.Mask.Graphics.PenWidth = 1 LastPicture.Mask.Graphics.ForeColor = &c000000 LastPicture.Mask.Graphics.DrawRect(0, 0, me.Width, me.Height) End If // Draw composited chart image LastWebPicture = LastPicture self.Picture = LastWebPicture // Process ImageMap data to support data point rollovers, etc. ImageMapString = Current.getHTMLImageMap("myurl" ) ImageMapHandler = New CDImageMapHandlerMBS(ImageMapString) End If End Sub
Function RenderPicture(Factor As Double, Width As Integer, Height As Integer) As Picture // Handle scaled redraw for printing Dim C As CDBaseChartMBS = Render(factor, Width, Height) 'If (C <> Nil) Then Return (C.makeChartPicture) // Error check If (C = Nil) Then Return (Nil) // Get in-memory version of the chart image in PNG format (supports transparency) Dim S As String S = C.makeChart(C.kPNG) // Error check If (S = "") Then Return (Nil) // Generate RB Picture from chart image data Dim P As Picture P = PNGStringToPictureMBS(S, 0) Return (P) End Function
Private Sub SendClickEvent() Dim Index as integer Dim Key, KeyValue As String Dim XLabel As String Dim XValue As String Dim DataSet As String Dim DataSetName As String Dim Value As String Dim Title As String Dim Sector As String Dim Label As String // Error check If (ImageMapHandler = Nil) Then Return // Do key/value pair priming calls Index = 0 Key = ImageMapHandler.getKey(Index) KeyValue = ImageMapHandler.getValue(Index) #if DebugBuild then // so you can look on all values in debugger dim debugDictionary as new Dictionary #endif Do #if DebugBuild then debugDictionary.value(key) = KeyValue #endif // NOTE: This is not the complete supported list of parameters; Refer to ChartDirector documentation on 'Parameter Substitution and Formatting' for additional parameters Select Case Key Case "xlabel" XLabel = KeyValue Case "x" XValue = KeyValue Case "dataset" DataSet = KeyValue Case "datasetname" DataSetName = KeyValue Case "value" Value = KeyValue Case "title" Title = KeyValue Case "sector" Sector = KeyValue Case "label" Label = KeyValue End Select Index = Index + 1 // Get next key/value pair Key = ImageMapHandler.getKey(Index) KeyValue = ImageMapHandler.getValue(Index) Loop Until Key.Len = 0 // Trigger click event ItemClicked(XLabel, Val(XValue), Val(DataSet), DataSetName, Val(Value), Title, Val(Sector), Label) End Sub
Note "About Properties"
AllowMove and AllowZoom must be enabled if you want to zoom and move. You need to use the viewport in your render code. If Border is true, a black line is drawn around the chart. If CleanGraphicsBeforeDrawing is true then the graphics object is cleared before something is drawn The OverlayPicture defines a picture which is drawn on top of the chart as a watermark. RenderWithTransparency will do redraws slower. The chart is rendered as PNG with mask and for every redraw we refresh the whole control. This may look bad on Windows. ZoomInRatio and ZoomOutRatio are used for zooming. This is how much we zoom on each click.
Note "Notes for Render Event"
Use the Width and Height you get and not the control's. Use the Factor to multiply all values so you get it properly scaled for printing. Use the ViewPort for zooming and moving.
Property Border As Boolean
Property Private Current As CDBaseChartMBS
Property Private ImageMapHandler As CDImageMapHandlerMBS
Property ImageMapString As string
Last map for debugging.
Property Private LastPicture As Picture
Property Private LastWebPicture As WebPicture
Property Private NeedClear As Boolean
Property OverlayPicture As Picture
Property ShowValueOnClick As Boolean
End Class
End Project

See also:

The items on this page are in the following plugins: MBS ChartDirector Plugin.


The biggest plugin in space...