* 继续更新UIBarChart

This commit is contained in:
Sunny 2020-06-18 22:21:04 +08:00
parent 327f5ae0d1
commit dcdb3f8874
9 changed files with 201 additions and 30 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -24,17 +24,17 @@
var series = new UIBarSeries();
series.Name = "Bar1";
series.AddData(+11);
series.AddData(+15);
series.AddData(+12);
series.AddData(+14);
series.AddData(+13);
series.AddData(11);
series.AddData(15);
series.AddData(12);
series.AddData(14);
series.AddData(13);
option.Series.Add(series);
series = new UIBarSeries();
series.Name = "Bar2";
series.AddData(-22);
series.AddData(0);
series.AddData(-28);
series.AddData(-25);
series.AddData(-23);
series.AddData(-24);
@ -47,6 +47,10 @@
option.XAxis.Data.Add("Fri");
option.ToolTip = new UIBarToolTip();
option.YAxis.Scale = true;
option.XAxis.Name = "日期";
option.YAxis.Name = "数值";
BarChart.SetOption(option);
}

View File

@ -37,7 +37,7 @@ namespace Sunny.UI
NeedDraw = true;
DrawBarWidth = DrawSize.Width * 1.0f / o.XAxis.Data.Count;
double min = Double.MaxValue;
double min = double.MaxValue;
double max = double.MinValue;
foreach (var series in o.Series)
{
@ -45,18 +45,14 @@ namespace Sunny.UI
max = Math.Max(max, series.Data.Max());
}
bool minZero = false;
bool maxZero = false;
if (min > 0 && max > 0 && !o.YAxis.Scale)
{
min = 0;
minZero = true;
}
if (min < 0 && max < 0 && !o.YAxis.Scale)
{
max = 0;
maxZero = true;
}
UIChartHelper.CalcDegreeScale(min, max, o.YAxis.SplitNumber,
@ -77,9 +73,10 @@ namespace Sunny.UI
for (int j = 0; j < series.Data.Count; j++)
{
if (minZero)
if (YAxisStart >= 0)
{
float h = Math.Abs((float)(DrawSize.Height * series.Data[j] / (end * interval)));
float h = Math.Abs((float)(DrawSize.Height * (series.Data[j]- start *interval) / ((end -start) * interval)));
Bars[i].Add(new BarInfo()
{
Rect = new RectangleF(
@ -88,9 +85,9 @@ namespace Sunny.UI
x2, h)
});
}
else if (maxZero)
else if (YAxisEnd<=0)
{
float h = Math.Abs((float)(DrawSize.Height * series.Data[j] / (start * interval)));
float h = Math.Abs((float)(DrawSize.Height * (end * interval-series.Data[j]) / ((end - start) * interval)));
Bars[i].Add(new BarInfo()
{
Rect = new RectangleF(
@ -119,24 +116,24 @@ namespace Sunny.UI
if (series.Data[j] >= 0)
{
float h = Math.Abs((float)(highH *series.Data[j] /highV ));
float h = Math.Abs((float)(highH * series.Data[j] / highV));
Bars[i].Add(new BarInfo()
{
Rect = new RectangleF(
barX + x1 * (i + 1) + x2 * i,
DrawOrigin.Y - lowH- h,
DrawOrigin.Y - lowH - h,
x2, h)
});
}
else
{
float h = Math.Abs((float)(lowH*series.Data[j] /lowV ));
float h = Math.Abs((float)(lowH * series.Data[j] / lowV));
Bars[i].Add(new BarInfo()
{
Rect = new RectangleF(
barX + x1 * (i + 1) + x2 * i,
DrawOrigin.Y - lowH+1,
x2, h-1)
DrawOrigin.Y - lowH + 1,
x2, h - 1)
});
}
}
@ -210,8 +207,15 @@ namespace Sunny.UI
tip.Size = new Size((int)Bars[0][selectIndex].Size.Width + 4, (int)Bars[0][selectIndex].Size.Height + 4);
}
tip.Left = e.Location.X + 15;
tip.Top = e.Location.Y + 20;
int x = e.Location.X + 15;
int y = e.Location.Y + 20;
if (e.Location.X + 15 + tip.Width > Width - BarOption.Grid.Right)
x = e.Location.X - tip.Width - 2;
if (e.Location.Y + 20 + tip.Height > Height - BarOption.Grid.Bottom)
y = e.Location.Y - tip.Height - 2;
tip.Left = x;
tip.Top = y;
if (!tip.Visible) tip.Visible = Bars[0][selectIndex].Tips.IsValid();
}
}
@ -304,7 +308,9 @@ namespace Sunny.UI
private void DrawAxis(Graphics g)
{
//g.DrawLine(ChartStyle.ForeColor, DrawOrigin, new Point(DrawOrigin.X + DrawSize.Width, DrawOrigin.Y));
if (YAxisStart>=0) g.DrawLine(ChartStyle.ForeColor, DrawOrigin, new Point(DrawOrigin.X + DrawSize.Width, DrawOrigin.Y));
if (YAxisEnd <= 0) g.DrawLine(ChartStyle.ForeColor, new Point(DrawOrigin.X, BarOption.Grid.Top), new Point(DrawOrigin.X + DrawSize.Width, BarOption.Grid.Top));
g.DrawLine(ChartStyle.ForeColor, DrawOrigin, new Point(DrawOrigin.X, DrawOrigin.Y - DrawSize.Height));
if (BarOption.XAxis.AxisTick.Show)
@ -350,9 +356,12 @@ namespace Sunny.UI
foreach (var data in BarOption.XAxis.Data)
{
SizeF sf = g.MeasureString(data, SubFont);
g.DrawString(data, SubFont, Color.FromArgb(150, ChartStyle.ForeColor), start - sf.Width / 2.0f, DrawOrigin.Y + BarOption.XAxis.AxisTick.Length);
g.DrawString(data, SubFont, ChartStyle.ForeColor, start - sf.Width / 2.0f, DrawOrigin.Y + BarOption.XAxis.AxisTick.Length);
start += DrawBarWidth;
}
SizeF sfname = g.MeasureString(BarOption.XAxis.Name, SubFont);
g.DrawString(BarOption.XAxis.Name,SubFont,ChartStyle.ForeColor, DrawOrigin.X +(DrawSize.Width-sfname.Width)/2.0f, DrawOrigin.Y + BarOption.XAxis.AxisTick.Length +sfname.Height);
}
if (BarOption.YAxis.AxisTick.Show)
@ -393,13 +402,21 @@ namespace Sunny.UI
float start = DrawOrigin.Y;
float DrawBarHeight = DrawSize.Height * 1.0f / (YAxisEnd - YAxisStart);
int idx = 0;
float wmax = 0;
for (int i = YAxisStart; i <= YAxisEnd; i++)
{
string label = BarOption.YAxis.AxisLabel.GetLabel(i * YAxisInterval, idx);
SizeF sf = g.MeasureString(label, SubFont);
wmax = Math.Max(wmax, sf.Width);
g.DrawString(label, SubFont, ChartStyle.ForeColor, DrawOrigin.X - BarOption.YAxis.AxisTick.Length - sf.Width, start - sf.Height / 2.0f);
start -= DrawBarHeight;
}
SizeF sfname = g.MeasureString(BarOption.YAxis.Name, SubFont);
int x = (int)(DrawOrigin.X - BarOption.YAxis.AxisTick.Length - wmax - sfname.Height);
int y = (int) (BarOption.Grid.Top + (DrawSize.Height - sfname.Width) / 2);
g.DrawString(BarOption.YAxis.Name,SubFont,ChartStyle.ForeColor, new Point(x,y),
new StringFormat(){Alignment = StringAlignment.Center}, 270);
}
}

View File

@ -53,7 +53,7 @@ namespace Sunny.UI
public int Left { get; set; } = 60;
public int Right { get; set; } = 60;
public int Top { get; set; } = 60;
public int Bottom { get; set; } = 40;
public int Bottom { get; set; } = 60;
}
public enum UIOrient

View File

@ -71,7 +71,7 @@ namespace Sunny.UI
SelectionMode = DataGridViewSelectionMode.FullRowSelect;
//禁止调整数据行行高
AllowUserToResizeRows = false;
//AllowUserToResizeRows = false;
//允许调整标题行行宽
AllowUserToResizeColumns = true;
@ -80,7 +80,7 @@ namespace Sunny.UI
RowHeadersVisible = false;
//禁止行多选
MultiSelect = false;
//MultiSelect = false;
//自动生成行
AutoGenerateColumns = true;

View File

@ -641,5 +641,155 @@ namespace Sunny.UI
}
}
}
public static void DrawString(this Graphics g, string s, Font font, Color color,
RectangleF layoutRectangle, StringFormat format, float angle)
{
using (Brush br= new SolidBrush(color))
{
g.DrawString(s,font,br,layoutRectangle,format,angle);
}
}
public static void DrawString(this Graphics g, string s, Font font, Color color,
PointF point, StringFormat format, float angle)
{
using (Brush br = new SolidBrush(color))
{
g.DrawString(s,font,br,point,format,angle);
}
}
/// <summary>
/// 绘制根据矩形旋转文本
/// </summary>
/// <param name="g">Graphics</param>
/// <param name="s">文本</param>
/// <param name="font">字体</param>
/// <param name="brush">填充</param>
/// <param name="layoutRectangle">局部矩形</param>
/// <param name="format">布局方式</param>
/// <param name="angle">角度</param>
public static void DrawString(this Graphics g, string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format, float angle)
{
// 求取字符串大小
SizeF size = g.MeasureString(s, font);
// 根据旋转角度,求取旋转后字符串大小
SizeF sizeRotate = ConvertSize(size, angle);
// 根据旋转后尺寸、布局矩形、布局方式计算文本旋转点
PointF rotatePt = GetRotatePoint(sizeRotate, layoutRectangle, format);
// 重设布局方式都为Center
StringFormat newFormat = new StringFormat(format);
newFormat.Alignment = StringAlignment.Center;
newFormat.LineAlignment = StringAlignment.Center;
// 绘制旋转后文本
g.DrawString(s, font, brush, rotatePt, newFormat, angle);
}
/// <summary>
/// 绘制根据点旋转文本,一般旋转点给定位文本包围盒中心点
/// </summary>
/// <param name="g">Graphics</param>
/// <param name="s">文本</param>
/// <param name="font">字体</param>
/// <param name="brush">填充</param>
/// <param name="point">旋转点</param>
/// <param name="format">布局方式</param>
/// <param name="angle">角度</param>
public static void DrawString(this Graphics g, string s, Font font, Brush brush, PointF point, StringFormat format, float angle)
{
// Save the matrix
Matrix mtxSave = g.Transform;
Matrix mtxRotate = g.Transform;
mtxRotate.RotateAt(angle, point);
g.Transform = mtxRotate;
g.DrawString(s, font, brush, point, format);
// Reset the matrix
g.Transform = mtxSave;
}
private static SizeF ConvertSize(SizeF size, float angle)
{
Matrix matrix = new Matrix();
matrix.Rotate(angle);
// 旋转矩形四个顶点
PointF[] pts = new PointF[4];
pts[0].X = -size.Width / 2f;
pts[0].Y = -size.Height / 2f;
pts[1].X = -size.Width / 2f;
pts[1].Y = size.Height / 2f;
pts[2].X = size.Width / 2f;
pts[2].Y = size.Height / 2f;
pts[3].X = size.Width / 2f;
pts[3].Y = -size.Height / 2f;
matrix.TransformPoints(pts);
// 求取四个顶点的包围盒
float left = float.MaxValue;
float right = float.MinValue;
float top = float.MaxValue;
float bottom = float.MinValue;
foreach (PointF pt in pts)
{
// 求取并集
if (pt.X < left)
left = pt.X;
if (pt.X > right)
right = pt.X;
if (pt.Y < top)
top = pt.Y;
if (pt.Y > bottom)
bottom = pt.Y;
}
SizeF result = new SizeF(right - left, bottom - top);
return result;
}
private static PointF GetRotatePoint(SizeF size, RectangleF layoutRectangle, StringFormat format)
{
PointF pt = new PointF();
switch (format.Alignment)
{
case StringAlignment.Near:
pt.X = layoutRectangle.Left + size.Width / 2f;
break;
case StringAlignment.Center:
pt.X = (layoutRectangle.Left + layoutRectangle.Right) / 2f;
break;
case StringAlignment.Far:
pt.X = layoutRectangle.Right - size.Width / 2f;
break;
}
switch (format.LineAlignment)
{
case StringAlignment.Near:
pt.Y = layoutRectangle.Top + size.Height / 2f;
break;
case StringAlignment.Center:
pt.Y = (layoutRectangle.Top + layoutRectangle.Bottom) / 2f;
break;
case StringAlignment.Far:
pt.Y = layoutRectangle.Bottom - size.Height / 2f;
break;
}
return pt;
}
}
}