⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bargraph.cs

📁 ASP.NET 建立和发布可自定义 Web 报表的指南
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Drawing;
using System.Collections;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace ASPNET.StarterKit.Chart
{
	//*********************************************************************
	//
	// BarGraph Class
	//
	// This class uses GDI+ to render Bar Chart.
	//
	//*********************************************************************

	public class BarGraph : Chart
	{
		private const float _graphLegendSpacer = 15F;
		private const int	_labelFontSize = 7;
		private const int	_legendFontSize = 9;
		private const float _legendRectangleSize = 10F;
		private const float _spacer = 5F;

		// Overall related members
		private Color	_backColor;
		private string	_fontFamily;
		private string	_longestTickValue = string.Empty;	// Used to calculate max value width
		private float	_maxTickValueWidth;					// Used to calculate left offset of bar graph
		private float	_totalHeight;
		private float	_totalWidth;
		
		// Graph related members
		private float	_barWidth;
		private float	_bottomBuffer;	// Space from bottom to x axis
		private bool	_displayBarData;	
		private Color	_fontColor;
		private float	_graphHeight;		
		private float	_graphWidth;
		private float	_maxValue = 0.0f;	// = final tick value * tick count
		private float	_scaleFactor;		// = _maxValue / _graphHeight
		private float	_spaceBtwBars;	// For now same as _barWidth
		private float	_topBuffer;		// Space from top to the top of y axis
		private float	_xOrigin;			// x position where graph starts drawing
		private float	_yOrigin;			// y position where graph starts drawing
		private string	_yLabel;
		private int		_yTickCount;
		private float	_yTickValue;		// Value for each tick = _maxValue/_yTickCount

		// Legend related members
		private bool	_displayLegend;
		private float	_legendWidth;
		private string	_longestLabel = string.Empty;	// Used to calculate legend width
		private float	_maxLabelWidth = 0.0f;

		public string FontFamily {
			get{ return _fontFamily; }
			set{ _fontFamily = value; }
		}

		public Color BackgroundColor {
			set{ _backColor = value; }
		}

		public int BottomBuffer {
			set { _bottomBuffer = Convert.ToSingle(value); }
		}

		public Color FontColor {
			set{ _fontColor = value; }
		}

		public int Height {
			get{ return Convert.ToInt32(_totalHeight); }
			set{ _totalHeight = Convert.ToSingle(value); }  
		}

		public int Width {
			get{ return Convert.ToInt32(_totalWidth); }
			set{ _totalWidth = Convert.ToSingle(value); }	
		}

		public bool ShowLegend {
			get{ return _displayLegend; }
			set{ _displayLegend = value; }
		}

		public bool ShowData {
			get{ return _displayBarData; }
			set{ _displayBarData = value; }
		}
		public int TopBuffer {
			set { _topBuffer = Convert.ToSingle(value); }
		}

		public string VerticalLabel {
			get{ return _yLabel; }
			set{ _yLabel = value; }
		}

		public int VerticalTickCount {
			get{ return _yTickCount; }
			set{ _yTickCount = value; }
		}

		public BarGraph()
		{
			AssignDefaultSettings();
		}

		public BarGraph(Color bgColor)
		{
			AssignDefaultSettings();
			BackgroundColor = bgColor;
		}

		//*********************************************************************
		//
		// This method collects all data points and calculate all the necessary dimensions 
		// to draw the bar graph.  It is the method called before invoking the Draw() method.
		// labels is the x values.
		// values is the y values.
		//
		//*********************************************************************

		public void CollectDataPoints(string[] labels, string[] values)
		{
			if (labels.Length == values.Length) 
			{
				for(int i=0; i<labels.Length; i++)
				{
					float temp = Convert.ToSingle(values[i]);
					string shortLbl = MakeShortLabel(labels[i]);

					// For now put 0.0 for start position and sweep size
					DataPoints.Add(new ChartItem(shortLbl, labels[i], temp, 0.0f, 0.0f, GetColor(i)));
				
					// Find max value from data; this is only temporary _maxValue
					if (_maxValue < temp) _maxValue = temp;

					// Find the longest description
					if (_displayLegend) 
					{
						string currentLbl = labels[i] + " (" + shortLbl + ")";
						float currentWidth = CalculateImgFontWidth(currentLbl, _legendFontSize, FontFamily);
						if(_maxLabelWidth < currentWidth)
						{
							_longestLabel = currentLbl;
							_maxLabelWidth = currentWidth;
						}
					}
				}

				CalculateTickAndMax();
				CalculateGraphDimension();
				CalculateBarWidth(DataPoints.Count, _graphWidth);
				CalculateSweepValues();
			}
			else
				throw new Exception("X data count is different from Y data count");
		}
		
		//*********************************************************************
		//
		// Same as above; called when user doesn't care about the x values
		//
		//*********************************************************************

		public void CollectDataPoints(string[] values)
		{
			string[] labels = values;
			CollectDataPoints(labels, values);
		}

		//*********************************************************************
		//
		// This method returns a bar graph bitmap to the calling function.  It is called after 
		// all dimensions and data points are calculated.
		//
		//*********************************************************************

		public override Bitmap Draw()
		{
			int height = Convert.ToInt32(_totalHeight);
			int width = Convert.ToInt32(_totalWidth);

			Bitmap bmp = new Bitmap(width, height);
			
			using(Graphics graph = Graphics.FromImage(bmp))
			{
				graph.CompositingQuality = CompositingQuality.HighQuality;
				graph.SmoothingMode = SmoothingMode.AntiAlias;

				// Set the background: need to draw one pixel larger than the bitmap to cover all area
				graph.FillRectangle(new SolidBrush(_backColor), -1, -1, bmp.Width+1, bmp.Height+1);

				DrawVerticalLabelArea(graph);
				DrawBars(graph);
				DrawXLabelArea(graph);
				if (_displayLegend) DrawLegend(graph);
			}

			return bmp;
		}

		//*********************************************************************
		//
		// This method draws all the bars for the graph.
		//
		//*********************************************************************

		private void DrawBars(Graphics graph)
		{
			SolidBrush brsFont = null;
			Font valFont = null;
			StringFormat sfFormat = null;

			try 
			{
				brsFont = new SolidBrush(_fontColor);
				valFont = new Font(_fontFamily, _labelFontSize);
				sfFormat = new StringFormat();
				sfFormat.Alignment = StringAlignment.Center;
				int i = 0;

				// Draw bars and the value above each bar
				foreach(ChartItem item in DataPoints)
				{
					using(SolidBrush barBrush = new SolidBrush(item.ItemColor))
					{
						float itemY = _yOrigin + _graphHeight - item.SweepSize;

						// When drawing, all position is relative to (_xOrigin, _yOrigin)
						graph.FillRectangle(barBrush, _xOrigin + item.StartPos, itemY, _barWidth, item.SweepSize);

						// Draw data value
						if (_displayBarData)
						{
							float startX = _xOrigin + (i * (_barWidth + _spaceBtwBars));  // This draws the value on center of the bar
							float startY = itemY - 2f - valFont.Height;					  // Positioned on top of each bar by 2 pixels
							RectangleF recVal = new RectangleF(startX, startY, _barWidth + _spaceBtwBars, valFont.Height);
							graph.DrawString(item.Value.ToString("#,###.##"), valFont, brsFont, recVal, sfFormat);	
						}
						i++;
					}
				}
			}
			finally 
			{
				if (brsFont != null) brsFont.Dispose();
				if (valFont != null) valFont.Dispose();
				if (sfFormat != null) sfFormat.Dispose();
			}
		}

		//*********************************************************************
		//
		// This method draws the y label, tick marks, tick values, and the y axis.
		//
		//*********************************************************************

		private void DrawVerticalLabelArea(Graphics graph)
		{
			Font lblFont = null;
			SolidBrush brs = null;
			StringFormat lblFormat = null;
			Pen pen = null;
			StringFormat sfVLabel = null;
			
			try
			{
				lblFont = new Font(_fontFamily, _labelFontSize);
				brs = new SolidBrush(_fontColor);
				lblFormat = new StringFormat();
				pen = new Pen(_fontColor);
				sfVLabel = new StringFormat();

				lblFormat.Alignment = StringAlignment.Near;

				// Draw vertical label at the top of y-axis and place it in the middle top of y-axis
				RectangleF recVLabel = new RectangleF(0f, _yOrigin-2*_spacer-lblFont.Height, _xOrigin*2, lblFont.Height);
				sfVLabel.Alignment = StringAlignment.Center;
				graph.DrawString(_yLabel, lblFont, brs, recVLabel, sfVLabel);

				// Draw all tick values and tick marks
				for (int i=0; i<_yTickCount; i++)
				{
					float currentY = _topBuffer + (i * _yTickValue/_scaleFactor);	// Position for tick mark
					float labelY = currentY-lblFont.Height/2;						// Place label in the middle of tick
					RectangleF lblRec = new RectangleF(_spacer, labelY, _maxTickValueWidth, lblFont.Height);
				
					float currentTick = _maxValue - i*_yTickValue;					// Calculate tick value from top to bottom
					graph.DrawString(currentTick.ToString("#,###.##"), lblFont, brs, lblRec, lblFormat);	// Draw tick value  
					graph.DrawLine(pen, _xOrigin, currentY, _xOrigin - 4.0f, currentY);						// Draw tick mark
				}

				// Draw y axis
				graph.DrawLine(pen, _xOrigin, _yOrigin, _xOrigin, _yOrigin + _graphHeight);
			}
			finally
			{
				if (lblFont != null) lblFont.Dispose();
				if (brs != null) brs.Dispose();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -