微图表(Sparklines)是一种小型的高分辨率折线图,用于展示数据的趋势走向。它们不会展示详细的数据,而只是显示一般的趋势。本文将解释如何在ASP.NET应用程序中创建和使用这种图表。
在ASP.NET页面(例如:sparkline.aspx)中,通过二进制输出生成图像。数据通过URL参数进入页面。
Dim sBgColor As String = "ffffff"
Dim sAvgLineColor As String = "gray"
Dim sLineColor As String = "#000000"
Dim sStdDevColor As String = "dcdcdc"
Dim bStdDev As Boolean = True
Dim sData As String = "1,2,3"
Dim iImageWidth As Integer = 200
Dim iImageHeight As Integer = 60
Dim iTopMargin As Integer = 5
Dim iBottomMargin As Integer = 5
Dim iLeftMargin As Integer = 5
Dim iRightMargin As Integer = 30
Dim iMax As Double = 0
Dim iMin As Double = 0
Dim iAvg As Double = 0
Dim iSum As Double = 0
Dim iStdDev As Double = 0
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SetVars()
Dim oData() As String = sData.Split(",")
If oData.Length <= 1 Then Exit Sub
SetAvg()
Dim oPoints(oData.Length - 1) As Point
Dim iScale As Double = (iImageHeight - (iTopMargin + iBottomMargin)) / Math.Abs(iMax - iMin)
Dim iStepWidth As Double = (iImageWidth - (iLeftMargin + iRightMargin)) / (oData.Length - 1)
If Not Double.IsInfinity(iScale) Then
For i As Integer = 0 To oData.Length - 1
Dim sValue As String = oData(i)
Dim iValue As Double = 0
If sValue <> "" And IsNumeric(sValue) Then iValue = CDbl(sValue)
Dim x As Integer = (i * iStepWidth) + iLeftMargin
Dim y As Integer = iImageHeight - (Math.Abs(iValue - iMin) * iScale) - iBottomMargin
oPoints(i) = New Point(x, y)
Next
End If
Dim oBitmap As Bitmap = New Bitmap(iImageWidth, iImageHeight)
Dim oPen As System.Drawing.Pen = New System.Drawing.Pen(GetColor(sLineColor))
Dim oAvgPen As System.Drawing.Pen = New System.Drawing.Pen(GetColor(sAvgLineColor))
Dim oGraphics As Graphics = Graphics.FromImage(oBitmap)
oGraphics.SmoothingMode = SmoothingMode.AntiAlias
oGraphics.FillRectangle(New SolidBrush(GetColor(sBgColor)), 0, 0, iImageWidth, iImageHeight)
Dim iMiddleY As Integer
If Not Double.IsInfinity(iScale) Then
iMiddleY = iImageHeight - (Math.Abs(iAvg - iMin) * iScale) - iBottomMargin
' StdDev
If bStdDev Then
Dim oRect As New Rectangle
oRect.Width = iImageWidth - (iRightMargin + iLeftMargin)
oRect.Height = iStdDev * iScale
oRect.X = iLeftMargin
oRect.Y = iMiddleY - (oRect.Height / 2)
oGraphics.FillRectangle(New SolidBrush(GetColor(sStdDevColor)), oRect)
End If
' Avg Line
oGraphics.DrawLine(oAvgPen, iLeftMargin, iMiddleY, iImageWidth - iRightMargin, iMiddleY)
' Lines
oGraphics.DrawLines(oPen, oPoints)
' Final Point
Dim oLastPoint As Point = oPoints(oPoints.Length - 1)
Dim oBrush As New SolidBrush(Color.Red)
oGraphics.FillPie(oBrush, oLastPoint.X - 2, oLastPoint.Y - 2, 4, 4, 0, 360)
' Final Value
Dim drawString As String = oData(oData.Length - 1)
Dim drawFont As New Font("Arial", 8)
Dim drawBrush As New SolidBrush(Color.Black)
oGraphics.DrawString(drawString, drawFont, drawBrush, oLastPoint.X + 2, oLastPoint.Y - 6)
Else
iMiddleY = iImageHeight / 2
oGraphics.DrawLine(oAvgPen, iLeftMargin, iMiddleY, iImageWidth - iRightMargin, iMiddleY)
End If
Response.ContentType = "image/jpeg"
oBitmap.Save(Response.OutputStream, ImageFormat.Jpeg)
oGraphics.Dispose()
oBitmap.Dispose()
End Sub
Private Sub SetAvg()
Dim oData() As String = sData.Split(",")
For i As Integer = 0 To oData.Length - 1
Dim sValue As String = oData(i)
Dim iValue As Double = 0
If sValue <> "" And IsNumeric(sValue) Then iValue = CDbl(sValue)
iSum += iValue
If i = 0 Then iMax = iValue : iMin = iValue
If iMax < iValue Then iMax = iValue
If iMin > iValue Then iMin = iValue
Next
iAvg = iSum / oData.Length
Dim iVar As Double
If bStdDev Then
For i As Integer = 0 To oData.Length - 1
Dim sValue As String = oData(i)
Dim iValue As Double = 0
If sValue <> "" And IsNumeric(sValue) Then iValue = CDbl(sValue)
iVar += Math.Pow(iValue - iAvg, 2)
Next
iStdDev = Math.Sqrt(iVar / oData.Length)
End If
End Sub
Private Sub SetVars()
If Request.QueryString("data") <> "" Then sData = Request.QueryString("data")
If Request.QueryString("StdDev") = "0" Then bStdDev = False
If Request.QueryString("bgcolor") <> "" Then sBgColor = Request.QueryString("bgcolor")
If Request.QueryString("avgcolor") <> "" Then sAvgLineColor = Request.QueryString("avgcolor")
If Request.QueryString("linecolor") <> "" Then sLineColor = Request.QueryString("linecolor")
If Request.QueryString("top") <> "" Then iTopMargin = Request.QueryString("top")
If Request.QueryString("bottom") <> "" Then iBottomMargin = Request.QueryString("bottom")
If Request.QueryString("left") <> "" Then iLeftMargin = Request.QueryString("left")
If Request.QueryString("right") <> "" Then iRightMargin = Request.QueryString("right")
If Request.QueryString("width") <> "" Then iImageWidth = Request.QueryString("width")
If Request.QueryString("height") <> "" Then iImageHeight = Request.QueryString("height")
End Sub
Private Function GetColor(ByVal sColor As String) As System.Drawing.Color
sColor = sColor.Replace("#", "")
Dim oColor As Color = Color.FromName(sColor)
Dim bColorEmpty As Boolean = oColor.R = 0 And oColor.G = 0 And oColor.B = 0
If bColorEmpty = False Then Return oColor
If sColor.Length <> 6 Then Return Color.White
Dim sRed As String = sColor.Substring(0, 2)
Dim sGreen As String = sColor.Substring(2, 2)
Dim sBlue As String = sColor.Substring(4, 2)
oColor = System.Drawing.Color.FromArgb(HexToInt(sRed), HexToInt(sGreen), HexToInt(sBlue))
Return oColor
End Function
Function HexToInt(ByVal hexString As String) As Integer
Return Integer.Parse(hexString, System.Globalization.NumberStyles.HexNumber, Nothing)
End Function
以下是图像页面(sparkline.aspx)可以接受的参数列表:
参数 | 描述 | 示例数据 |
---|---|---|
data | 要可视化的逗号分隔数据 | 1,10,10,1 |
StdDev | 标准差带 | 1-显示, 0-隐藏 |
bgcolor | 背景颜色 | yellow |
avgcolor | 平均线颜色 | red |
linecolor | 线条颜色 | red |
top | 顶部边距 | 5 |
bottom | 底部边距 | 5 |
left | 左侧边距 | 5 |
right | 右侧边距 | 5 |
width | 图表宽度 | 200 |
height | 图表高度 | 60 |
Dim sConnectionString As String = "Provider=SQLOLEDB.1;Password=test;User ID=test;Initial Catalog=Northwind;Data Source=(local)"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Response.Expires = 0
End Sub
Public Sub ShowSparklines()
Response.Write("")
Response.Write("Category 1998 Sales ")
Dim sSql As String = "SELECT CategoryID, CategoryName FROM Categories"
Dim dr As OleDbDataReader = GetDataReader(sSql)
While dr.Read
Response.Write("" & dr.GetValue(dr.GetOrdinal("CategoryName")) & " ")
Dim sCategoryID As String = dr.GetValue(dr.GetOrdinal("CategoryID")) & ""
Response.Write("" & GetSparkLine(sCategoryID, 1998) & " ")
End While
dr.Close()
Response.Write("
")
End Sub
Private Function GetSparkLine(ByVal sCategoryID As String, ByVal sYear As String) As String
Dim sSql As String = "SELECT o.OrderDate, SUM(od.UnitPrice * od.Quantity) AS Sales FROM Orders o INNER JOIN [Order Details] od ON o.OrderID = od.OrderID INNER JOIN Products p ON od.ProductID = p.ProductID WHERE p.CategoryID = " & sCategoryID & " AND YEAR(o.OrderDate) = 1998 GROUP BY o.OrderDate ORDER BY o.OrderDate"
Dim dr As OleDbDataReader = GetDataReader(sSql)
Dim sData As String = ""
While dr.Read
If sData <> "" Then sData += ","
sData += dr.GetValue(dr.GetOrdinal("Sales")) & ""
End While
dr.Close()
Dim iWidth As Integer = 150
Dim iHeight As Integer = 50
Return ""
End Function
Friend Function GetDataReader(ByVal sSql As String) As OleDb.OleDbDataReader
Dim cn As New OleDb.OleDbConnection(sConnectionString)
cn.Open()
Dim cm As New OleDb.OleDbCommand(sSql, cn)
Return cm.ExecuteReader(CommandBehavior.CloseConnection)
End Function