在网页上创建和显示漏斗图






4.58/5 (16投票s)
如何使用 C# 和 ASP.NET 在网页上创建和显示漏斗图。
引言
有时,为了提供更好的用户体验,需要以漏斗图的形式显示数据(财务数据),并且开发者可能需要从头开始编写漏斗图的显示代码。以下文章将帮助您编写漏斗图代码并在网页上显示它们。
使用代码
在创建漏斗图时,我们将它分成不同的切片。每个切片代表一个不同的阶段。在下面的示例中,每个切片都以不同的颜色显示。请查看下面的代码。代码中使用了 System.Drawing
和 System.Drawing.Imaging
命名空间来绘制漏斗切片并将它们组合在一起形成漏斗。
// This structure holds the details of each of the slices
public struct Slice
{
public string stageName;
public int value;
public double dollars;
public Point[] coordinates;
public Color color;
}
private Color[] colorPalette = new Color[]
{Color.LightSkyBlue,Color.LightGreen,
Color.PaleVioletRed,Color.SteelBlue};
// Following constants are used to initialize
// the funnel maximum height, width, slice gap
private const int FUNNEL_HEIGHT = 106;
private const int IMAGE_WIDTH = 291;
private const int IMAGE_HEIGHT = 160;
private const int SLICE_GAP = 1;
private Slice[] funnelSlices;
/// <summary>
/// This method initializes the funnel
/// </summary>
public void InitFunnel(int count)
{
try
{
maxSlice = count;
funnelSlices = new Slice[count];
chartBMP = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT,
PixelFormat.Format32bppArgb);
graphicsObj = Graphics.FromImage(chartBMP);
// Draw the background
graphicsObj.FillRectangle(new SolidBrush(Color.White),
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
}
catch (Exception ex)
{
throw new Exception("Error initialising funnel", ex);
}
}
// 0--------------3
// \ /
// \ /
// 1\_______/2
/// <summary>
/// Calculates the coordinates of the slice
/// </summary>
private void GetCoordinates(int sliceIndex)
{
int sliceHeight;
// Calculate the top points ie, 0 & 3
if (sliceIndex == 0)
{
// The top 2 points are same as the funnel
funnelSlices[sliceIndex].coordinates[0] = FUNNEL_BOUNDS[0];
funnelSlices[sliceIndex].coordinates[3] = FUNNEL_BOUNDS[3];
}
else
{
// The top 2 points are same
// as the bottom 2 points of the previous slice
funnelSlices[sliceIndex].coordinates[0] =
funnelSlices[sliceIndex - 1].coordinates[1];
funnelSlices[sliceIndex].coordinates[3] =
funnelSlices[sliceIndex - 1].coordinates[2];
}
// Calculate the bottom 2 points ie, 1 & 2
if (sliceIndex == funnelSlices.Length - 1)
{
// The bottom 2 points are same as the funnel
funnelSlices[sliceIndex].coordinates[1] = FUNNEL_BOUNDS[1];
funnelSlices[sliceIndex].coordinates[2] = FUNNEL_BOUNDS[2];
}
else
{
sliceHeight = GetHeight(sliceIndex);
// Calculate the other 2 points using the 2 point equation
// Use Point 0 & 1 of the funnel to calculate point 1 of the slice
funnelSlices[sliceIndex].coordinates[1].Y =
funnelSlices[sliceIndex].coordinates[0].Y + sliceHeight;
funnelSlices[sliceIndex].coordinates[1].X =
GetX(
FUNNEL_BOUNDS[0].X, FUNNEL_BOUNDS[0].Y,
FUNNEL_BOUNDS[1].X, FUNNEL_BOUNDS[1].Y,
funnelSlices[sliceIndex].coordinates[1].Y);
// Use Point 2 & 3 of the funnel to calculate point 2 of the slice
funnelSlices[sliceIndex].coordinates[2].Y =
funnelSlices[sliceIndex].coordinates[0].Y + sliceHeight;
funnelSlices[sliceIndex].coordinates[2].X =
GetX(
FUNNEL_BOUNDS[2].X, FUNNEL_BOUNDS[2].Y,
FUNNEL_BOUNDS[3].X, FUNNEL_BOUNDS[3].Y,
funnelSlices[sliceIndex].coordinates[2].Y);
}
}
/// <summary>
/// This method returns the x coordinate on the line defined by
/// (x1, y1) and (x2, y2) for a given y.
/// </summary>
private int GetX(int x1, int y1, int x2, int y2, int y)
{
return (x2 - x1) * (y - y1) / (y2 - y1) + x1;
}
/// <summary>
/// Adds required slice with the name, value, associated revenue and color
/// </summary>
public void AddSlice(string name, int value, double dollars, Color sliceClr)
{
// Throw exception if it exceeds the max
// Create a new slice object and set the values
Slice newSlice = new Slice();
newSlice.coordinates = new Point[4];
newSlice.stageName = name;
newSlice.value = value;
newSlice.dollars = dollars;
newSlice.color = sliceClr;
// Place it in the Slice[] array at appropriate location
funnelSlices[curSlice++] = newSlice;
// Update the total value
totalVal += value;
}
/// <summary>
/// This method adds the gaps between the slices
/// </summary>
public void AddGaps(int i)
{
funnelSlices[i].coordinates[0].Y =
funnelSlices[i].coordinates[0].Y + i * SLICE_GAP;
funnelSlices[i].coordinates[1].Y =
funnelSlices[i].coordinates[1].Y + i * SLICE_GAP;
funnelSlices[i].coordinates[2].Y =
funnelSlices[i].coordinates[2].Y + i * SLICE_GAP;
funnelSlices[i].coordinates[3].Y =
funnelSlices[i].coordinates[3].Y + i * SLICE_GAP;
}
/// <summary>
/// This method plots the graph.
/// To be called after all the values have been initialized
/// </summary>
public void PlotGraph()
{
int i;
SizeF strSz;
string label;
labelTop = FUNNEL_BOUNDS[0].Y;
// Throw exception if all slices not initialised
// Repeat the following steps for each of the slices
for (i = 0; i < maxSlice; i++)
{
// Get the coordinates of the slice
GetCoordinates(i);
}
// Get the height of the font
int labelHeight = (int)graphicsObj.MeasureString("B",labelFont).Height;
for (i = 0; i < maxSlice; i++)
{
// Add gaps between slices
AddGaps(i);
// Calculate label top (and bottom for next loop)
labelTop = (funnelSlices[i].coordinates[0].Y > labelBottom + 1 ?
funnelSlices[i].coordinates[0].Y : labelBottom + 1);
labelBottom = labelTop + labelHeight;
// Plot the graph
graphicsObj.FillPolygon(new SolidBrush(funnelSlices[i].color),
funnelSlices[i].coordinates);
// Add the stage name label on the left
strSz = graphicsObj.MeasureString(funnelSlices[i].stageName, labelFont);
graphicsObj.DrawString(funnelSlices[i].stageName, labelFont,
fontBrush, funnelSlices[i].coordinates[0].X -
strSz.Width, labelTop);
// Add the value label on the right
label = ((funnelSlices[i].dollars)).ToString("C0") + "(" +
funnelSlices[i].value.ToString() + ")";
graphicsObj.DrawString(label, labelFont, fontBrush,
funnelSlices[i].coordinates[3].X,labelTop);
SummationValue += float.Parse(funnelSlices[i].dollars.ToString());
TotalDealsOpps += int.Parse(funnelSlices[i].value.ToString());
}
label = (SummationValue).ToString("C0") + "(" +
TotalDealsOpps.ToString() + ")";
strSz = graphicsObj.MeasureString(label, labelFont);
int funnelWidth = (FUNNEL_BOUNDS[3].X - FUNNEL_BOUNDS[0].X);
int labelX = FUNNEL_BOUNDS[0].X + (int)(funnelWidth / 2 - strSz.Width / 2);
int labelY = (int)(IMAGE_HEIGHT - strSz.Height );
graphicsObj.DrawString(label, labelFont, fontBrush, labelX, labelY);
// Saves the created funnel as an image in Response.OutStream
Response.ContentType = IMAGE_FORMAT;
chartBMP.Save(Response.OutputStream, ImageFormat.Jpeg);
}
以上所有代码都应放置在 ASPX 页面的代码隐藏文件中。此页面的页面加载事件将加载要显示的数据。请仔细阅读上面的代码以及附件文件。要在网页上显示漏斗图,可以使用以下代码
<div class="blockBody">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
<img src="FunnelChart.aspx" />
<!-- FunnelChart.aspx is the page where the above
code is placed as code behind -->
</td>
</tr>
</table>
</div>
关注点
我研究了许多现有的漏斗图代码,但发现将其编码并在网页上显示更有趣也更容易。当我们的项目上线时,我的客户非常赞赏这项工作。