* UILineChart:继续优化
This commit is contained in:
parent
552d683df3
commit
1e09ae19b0
Binary file not shown.
BIN
Bin/SunnyUI.dll
BIN
Bin/SunnyUI.dll
Binary file not shown.
BIN
Bin/SunnyUI.pdb
BIN
Bin/SunnyUI.pdb
Binary file not shown.
30
SunnyUI.Demo/Charts/FLineChart.Designer.cs
generated
30
SunnyUI.Demo/Charts/FLineChart.Designer.cs
generated
@ -33,7 +33,7 @@
|
|||||||
this.uiImageButton2 = new Sunny.UI.UIImageButton();
|
this.uiImageButton2 = new Sunny.UI.UIImageButton();
|
||||||
this.uiImageButton1 = new Sunny.UI.UIImageButton();
|
this.uiImageButton1 = new Sunny.UI.UIImageButton();
|
||||||
this.uiLine1 = new Sunny.UI.UILine();
|
this.uiLine1 = new Sunny.UI.UILine();
|
||||||
this.uiLineChart1 = new Sunny.UI.UILineChart();
|
this.LineChart = new Sunny.UI.UILineChart();
|
||||||
this.PagePanel.SuspendLayout();
|
this.PagePanel.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).BeginInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).BeginInit();
|
||||||
@ -47,7 +47,7 @@
|
|||||||
this.PagePanel.Controls.Add(this.uiImageButton2);
|
this.PagePanel.Controls.Add(this.uiImageButton2);
|
||||||
this.PagePanel.Controls.Add(this.uiImageButton1);
|
this.PagePanel.Controls.Add(this.uiImageButton1);
|
||||||
this.PagePanel.Controls.Add(this.uiLine1);
|
this.PagePanel.Controls.Add(this.uiLine1);
|
||||||
this.PagePanel.Controls.Add(this.uiLineChart1);
|
this.PagePanel.Controls.Add(this.LineChart);
|
||||||
this.PagePanel.Size = new System.Drawing.Size(800, 539);
|
this.PagePanel.Size = new System.Drawing.Size(800, 539);
|
||||||
//
|
//
|
||||||
// uiSymbolButton1
|
// uiSymbolButton1
|
||||||
@ -62,6 +62,7 @@
|
|||||||
this.uiSymbolButton1.Symbol = 61952;
|
this.uiSymbolButton1.Symbol = 61952;
|
||||||
this.uiSymbolButton1.TabIndex = 34;
|
this.uiSymbolButton1.TabIndex = 34;
|
||||||
this.uiSymbolButton1.Text = "数据";
|
this.uiSymbolButton1.Text = "数据";
|
||||||
|
this.uiSymbolButton1.Click += new System.EventHandler(this.uiSymbolButton1_Click);
|
||||||
//
|
//
|
||||||
// uiImageButton3
|
// uiImageButton3
|
||||||
//
|
//
|
||||||
@ -113,18 +114,19 @@
|
|||||||
this.uiLine1.Text = "UIBarChart";
|
this.uiLine1.Text = "UIBarChart";
|
||||||
this.uiLine1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
this.uiLine1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
//
|
//
|
||||||
// uiLineChart1
|
// LineChart
|
||||||
//
|
//
|
||||||
this.uiLineChart1.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
|
this.LineChart.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
|
||||||
this.uiLineChart1.Font = new System.Drawing.Font("微软雅黑", 12F);
|
this.LineChart.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||||
this.uiLineChart1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
|
this.LineChart.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
|
||||||
this.uiLineChart1.Location = new System.Drawing.Point(30, 48);
|
this.LineChart.Location = new System.Drawing.Point(30, 48);
|
||||||
this.uiLineChart1.MinimumSize = new System.Drawing.Size(1, 1);
|
this.LineChart.MinimumSize = new System.Drawing.Size(1, 1);
|
||||||
this.uiLineChart1.Name = "uiLineChart1";
|
this.LineChart.Name = "LineChart";
|
||||||
this.uiLineChart1.Option = null;
|
this.LineChart.Option = null;
|
||||||
this.uiLineChart1.Size = new System.Drawing.Size(670, 400);
|
this.LineChart.Size = new System.Drawing.Size(670, 400);
|
||||||
this.uiLineChart1.TabIndex = 35;
|
this.LineChart.TabIndex = 35;
|
||||||
this.uiLineChart1.Text = "uiLineChart1";
|
this.LineChart.Text = "uiLineChart1";
|
||||||
|
this.LineChart.PointValue += new Sunny.UI.UILineChart.OnPointValue(this.LineChart_PointValue);
|
||||||
//
|
//
|
||||||
// FLineChart
|
// FLineChart
|
||||||
//
|
//
|
||||||
@ -149,6 +151,6 @@
|
|||||||
private UIImageButton uiImageButton2;
|
private UIImageButton uiImageButton2;
|
||||||
private UIImageButton uiImageButton1;
|
private UIImageButton uiImageButton1;
|
||||||
private UILine uiLine1;
|
private UILine uiLine1;
|
||||||
private UILineChart uiLineChart1;
|
private UILineChart LineChart;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,8 @@
|
|||||||
namespace Sunny.UI.Demo.Charts
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Sunny.UI.Demo.Charts
|
||||||
{
|
{
|
||||||
public partial class FLineChart : UITitlePage
|
public partial class FLineChart : UITitlePage
|
||||||
{
|
{
|
||||||
@ -6,5 +10,63 @@
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void uiSymbolButton1_Click(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
UILineOption option = new UILineOption();
|
||||||
|
option.Title = new UITitle();
|
||||||
|
option.Title.Text = "SunnyUI";
|
||||||
|
option.Title.SubText = "LineChart";
|
||||||
|
|
||||||
|
option.XAxisType = UIAxisType.Time;
|
||||||
|
|
||||||
|
var series = option.AddSeries(new UILineSeries("Line1"));
|
||||||
|
DateTime dt = new DateTime(2020, 10, 4);
|
||||||
|
series.Add(dt.AddHours(0), 1.2);
|
||||||
|
series.Add(dt.AddHours(0.1), 2.2);
|
||||||
|
series.Add(dt.AddHours(0.2), 3.2);
|
||||||
|
series.Add(dt.AddHours(0.3), 4.2);
|
||||||
|
series.Add(dt.AddHours(0.4), 3.2);
|
||||||
|
series.Add(dt.AddHours(0.5), 2.2);
|
||||||
|
series.Symbol = UILinePointSymbol.Square;
|
||||||
|
series.SymbolSize = 4;
|
||||||
|
series.SymbolLineWidth = 2;
|
||||||
|
series.SymbolColor = Color.Red;
|
||||||
|
|
||||||
|
series = option.AddSeries(new UILineSeries("Line2"));
|
||||||
|
series.Add(dt.AddHours(0.3), 3.3);
|
||||||
|
series.Add(dt.AddHours(0.4), 2.3);
|
||||||
|
series.Add(dt.AddHours(0.5), 2.3);
|
||||||
|
series.Add(dt.AddHours(0.6), 1.3);
|
||||||
|
series.Add(dt.AddHours(0.7), 2.3);
|
||||||
|
series.Add(dt.AddHours(0.8), 4.3);
|
||||||
|
series.Symbol = UILinePointSymbol.Star;
|
||||||
|
series.SymbolSize = 4;
|
||||||
|
series.SymbolLineWidth = 2;
|
||||||
|
series.SymbolColor = Color.Red;
|
||||||
|
series.Smooth = true;
|
||||||
|
|
||||||
|
// option.XAxis.Min = new DateTimeInt64(dt.AddDays(-1));
|
||||||
|
// option.XAxis.Max = new DateTimeInt64(dt.AddDays(1));
|
||||||
|
// option.XAxis.MaxAuto = false;
|
||||||
|
// option.XAxis.MinAuto = false;
|
||||||
|
|
||||||
|
option.XAxis.Name = "数值";
|
||||||
|
option.YAxis.Name = "数值";
|
||||||
|
|
||||||
|
LineChart.SetOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LineChart_PointValue(object sender, System.Collections.Generic.List<UILineSelectPoint> points)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (var point in points)
|
||||||
|
{
|
||||||
|
sb.Append(point.Name + ", " + point.Index + ", " + point.X + ", " + point.Y);
|
||||||
|
sb.Append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(sb.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,11 @@ namespace Sunny.UI
|
|||||||
double max = double.MinValue;
|
double max = double.MinValue;
|
||||||
foreach (var series in BarOption.Series)
|
foreach (var series in BarOption.Series)
|
||||||
{
|
{
|
||||||
min = Math.Min(min, series.Data.Min());
|
if (series.Data.Count > 0)
|
||||||
max = Math.Max(max, series.Data.Max());
|
{
|
||||||
|
min = Math.Min(min, series.Data.Min());
|
||||||
|
max = Math.Max(max, series.Data.Max());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min > 0 && max > 0 && !BarOption.YAxis.Scale) min = 0;
|
if (min > 0 && max > 0 && !BarOption.YAxis.Scale) min = 0;
|
||||||
|
@ -159,15 +159,31 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
public event DoFormatter Formatter;
|
public event DoFormatter Formatter;
|
||||||
|
|
||||||
public string GetLabel(double value, int index)
|
public string GetLabel(double value, int index, UIAxisType axisType = UIAxisType.Value)
|
||||||
{
|
{
|
||||||
return Formatter != null ? Formatter?.Invoke(value, index) : value.ToString("F" + DecimalCount);
|
switch (axisType)
|
||||||
|
{
|
||||||
|
case UIAxisType.Value:
|
||||||
|
return Formatter != null ? Formatter?.Invoke(value, index) : value.ToString("F" + DecimalCount);
|
||||||
|
case UIAxisType.Time:
|
||||||
|
DateTimeInt64 dt = new DateTimeInt64((long)value);
|
||||||
|
return Formatter != null ? Formatter?.Invoke(dt, index) : (DateTimeFormat.IsNullOrEmpty() ? dt.ToString() : dt.ToString(DateTimeFormat));
|
||||||
|
case UIAxisType.Category:
|
||||||
|
return Formatter != null ? Formatter?.Invoke(value, index) : value.ToString("F0");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.ToString("F2");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 小数位个数,Formatter不为空时以Formatter为准
|
/// 小数位个数,Formatter不为空时以Formatter为准
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DecimalCount { get; set; } = 0;
|
public int DecimalCount { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 日期格式化字符串,Formatter不为空时以Formatter为准
|
||||||
|
/// </summary>
|
||||||
|
public string DateTimeFormat { get; set; } = "HH:mm";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UIAxisTick
|
public class UIAxisTick
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
using Sunny.UI.Charts;
|
using System;
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace Sunny.UI
|
namespace Sunny.UI
|
||||||
{
|
{
|
||||||
@ -42,13 +43,13 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
foreach (var series in LineOption.Series.Values)
|
foreach (var series in LineOption.Series.Values)
|
||||||
{
|
{
|
||||||
series.Points.Clear();
|
series.ClearPoints();
|
||||||
|
|
||||||
for (int i = 0; i < series.XData.Count; i++)
|
for (int i = 0; i < series.XData.Count; i++)
|
||||||
{
|
{
|
||||||
float x = (float)(series.XData[i] - XAxisStart) * 1.0f * DrawSize.Width / (XAxisEnd - XAxisStart);
|
float x = (float)((series.XData[i] - XAxisStart * XAxisInterval) * 1.0f * DrawSize.Width / XAxisInterval / (XAxisEnd - XAxisStart));
|
||||||
float y = (float)(series.YData[i] - YAxisStart) * 1.0f * DrawSize.Height / (YAxisEnd - YAxisStart);
|
float y = (float)((series.YData[i] - YAxisStart * YAxisInterval) * 1.0f * DrawSize.Height / YAxisInterval / (YAxisEnd - YAxisStart));
|
||||||
series.Points.Add(new PointF(DrawOrigin.X + x, DrawOrigin.Y - y));
|
series.AddPoint(new PointF(DrawOrigin.X + x, DrawOrigin.Y - y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,8 +63,11 @@ namespace Sunny.UI
|
|||||||
double max = double.MinValue;
|
double max = double.MinValue;
|
||||||
foreach (var series in LineOption.Series.Values)
|
foreach (var series in LineOption.Series.Values)
|
||||||
{
|
{
|
||||||
min = Math.Min(min, series.YData.Min());
|
if (series.DataCount > 0)
|
||||||
max = Math.Max(max, series.YData.Max());
|
{
|
||||||
|
min = Math.Min(min, series.YData.Min());
|
||||||
|
max = Math.Max(max, series.YData.Max());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min > 0 && max > 0 && !LineOption.YAxis.Scale) min = 0;
|
if (min > 0 && max > 0 && !LineOption.YAxis.Scale) min = 0;
|
||||||
@ -93,8 +97,8 @@ namespace Sunny.UI
|
|||||||
max = Math.Max(max, series.XData.Max());
|
max = Math.Max(max, series.XData.Max());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min > 0 && max > 0 && !LineOption.XAxis.Scale) min = 0;
|
if (min > 0 && max > 0 && !LineOption.XAxis.Scale && LineOption.XAxisType == UIAxisType.Value) min = 0;
|
||||||
if (min < 0 && max < 0 && !LineOption.XAxis.Scale) max = 0;
|
if (min < 0 && max < 0 && !LineOption.XAxis.Scale && LineOption.XAxisType == UIAxisType.Value) max = 0;
|
||||||
if (!LineOption.XAxis.MaxAuto) max = LineOption.XAxis.Max;
|
if (!LineOption.XAxis.MaxAuto) max = LineOption.XAxis.Max;
|
||||||
if (!LineOption.XAxis.MinAuto) min = LineOption.XAxis.Min;
|
if (!LineOption.XAxis.MinAuto) min = LineOption.XAxis.Min;
|
||||||
|
|
||||||
@ -104,12 +108,23 @@ namespace Sunny.UI
|
|||||||
min = 0;
|
min = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIChartHelper.CalcDegreeScale(min, max, LineOption.XAxis.SplitNumber,
|
if (LineOption.XAxisType == UIAxisType.Value || LineOption.XAxisType == UIAxisType.Category)
|
||||||
out int startX, out int endX, out double intervalX);
|
{
|
||||||
|
UIChartHelper.CalcDegreeScale(min, max, LineOption.XAxis.SplitNumber,
|
||||||
|
out int startX, out int endX, out double intervalX);
|
||||||
|
XAxisStart = startX;
|
||||||
|
XAxisEnd = endX;
|
||||||
|
XAxisInterval = intervalX;
|
||||||
|
}
|
||||||
|
|
||||||
XAxisStart = startX;
|
if (LineOption.XAxisType == UIAxisType.Time)
|
||||||
XAxisEnd = endX;
|
{
|
||||||
XAxisInterval = intervalX;
|
UIChartHelper.CalcDateTimeDegreeScale(min, max, LineOption.XAxis.SplitNumber,
|
||||||
|
out int startX, out int endX, out double intervalX);
|
||||||
|
XAxisStart = startX;
|
||||||
|
XAxisEnd = endX;
|
||||||
|
XAxisInterval = intervalX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
@ -131,15 +146,31 @@ namespace Sunny.UI
|
|||||||
option.Title.Text = "SunnyUI";
|
option.Title.Text = "SunnyUI";
|
||||||
option.Title.SubText = "LineChart";
|
option.Title.SubText = "LineChart";
|
||||||
|
|
||||||
option.AddSeries(new UILineSeries("Line"));
|
var series = option.AddSeries(new UILineSeries("Line1"));
|
||||||
option.AddData("Line", 0, 1);
|
series.Add(0, 1.2);
|
||||||
option.AddData("Line", 1, 2);
|
series.Add(1.1, 2.2);
|
||||||
option.AddData("Line", 2, 3);
|
series.Add(2.2, 3.2);
|
||||||
option.AddData("Line", 3, 4);
|
series.Add(3.3, 4.2);
|
||||||
option.AddData("Line", 4, 3);
|
series.Add(4.4, 3.2);
|
||||||
option.AddData("Line", 5, 2);
|
series.Add(5.5, 2.2);
|
||||||
|
series.Symbol = UILinePointSymbol.Square;
|
||||||
|
series.SymbolSize = 4;
|
||||||
|
series.SymbolLineWidth = 1;
|
||||||
|
series.SymbolColor = Color.Red;
|
||||||
|
|
||||||
option.XAxis.Name = "日期";
|
series = option.AddSeries(new UILineSeries("Line2"));
|
||||||
|
series.Add(0.3, 3.3);
|
||||||
|
series.Add(1.3, 2.3);
|
||||||
|
series.Add(2.3, 2.3);
|
||||||
|
series.Add(3.3, 1.3);
|
||||||
|
series.Add(4.3, 2.3);
|
||||||
|
series.Add(5.3, 4.3);
|
||||||
|
series.Symbol = UILinePointSymbol.Plus;
|
||||||
|
series.SymbolSize = 4;
|
||||||
|
series.SymbolLineWidth = 1;
|
||||||
|
series.SymbolColor = Color.Red;
|
||||||
|
|
||||||
|
option.XAxis.Name = "数值";
|
||||||
option.YAxis.Name = "数值";
|
option.YAxis.Name = "数值";
|
||||||
|
|
||||||
emptyOption = option;
|
emptyOption = option;
|
||||||
@ -204,7 +235,7 @@ namespace Sunny.UI
|
|||||||
float wmax = 0;
|
float wmax = 0;
|
||||||
for (int i = XAxisStart; i <= XAxisEnd; i++)
|
for (int i = XAxisStart; i <= XAxisEnd; i++)
|
||||||
{
|
{
|
||||||
string label = LineOption.XAxis.AxisLabel.GetLabel(i * XAxisInterval, idx);
|
string label = LineOption.XAxis.AxisLabel.GetLabel(i * XAxisInterval, idx, LineOption.XAxisType);
|
||||||
SizeF sf = g.MeasureString(label, SubFont);
|
SizeF sf = g.MeasureString(label, SubFont);
|
||||||
wmax = Math.Max(wmax, sf.Width);
|
wmax = Math.Max(wmax, sf.Width);
|
||||||
g.DrawString(label, SubFont, ChartStyle.ForeColor, start - sf.Width / 2.0f,
|
g.DrawString(label, SubFont, ChartStyle.ForeColor, start - sf.Width / 2.0f,
|
||||||
@ -277,10 +308,80 @@ namespace Sunny.UI
|
|||||||
Color color = series.Color;
|
Color color = series.Color;
|
||||||
if (!series.CustomColor) color = ChartStyle.GetColor(idx);
|
if (!series.CustomColor) color = ChartStyle.GetColor(idx);
|
||||||
|
|
||||||
if (series.Smooth)
|
using (Pen pen = new Pen(color, series.Width))
|
||||||
g.DrawCurve(color, series.Points.ToArray(), true);
|
{
|
||||||
else
|
g.SetHighQuality();
|
||||||
g.DrawLines(series.Color, series.Points.ToArray(), true);
|
if (series.Smooth)
|
||||||
|
g.DrawCurve(pen, series.Points.ToArray());
|
||||||
|
else
|
||||||
|
g.DrawLines(pen, series.Points.ToArray());
|
||||||
|
g.SetDefaultQuality();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (series.Symbol != UILinePointSymbol.None)
|
||||||
|
{
|
||||||
|
using (Brush br = new SolidBrush(ChartStyle.BackColor))
|
||||||
|
using (Pen pn = new Pen(series.SymbolColor, series.SymbolLineWidth))
|
||||||
|
{
|
||||||
|
foreach (var p in series.Points)
|
||||||
|
{
|
||||||
|
switch (series.Symbol)
|
||||||
|
{
|
||||||
|
case UILinePointSymbol.Square:
|
||||||
|
g.FillRectangle(br, p.X - series.SymbolSize, p.Y - series.SymbolSize, series.SymbolSize * 2, series.SymbolSize * 2);
|
||||||
|
g.DrawRectangle(pn, p.X - series.SymbolSize, p.Y - series.SymbolSize, series.SymbolSize * 2, series.SymbolSize * 2);
|
||||||
|
break;
|
||||||
|
case UILinePointSymbol.Diamond:
|
||||||
|
{
|
||||||
|
PointF pt1 = new PointF(p.X - series.SymbolSize, p.Y);
|
||||||
|
PointF pt2 = new PointF(p.X, p.Y - series.SymbolSize);
|
||||||
|
PointF pt3 = new PointF(p.X + series.SymbolSize, p.Y);
|
||||||
|
PointF pt4 = new PointF(p.X, p.Y + series.SymbolSize);
|
||||||
|
PointF[] pts = { pt1, pt2, pt3, pt4, pt1 };
|
||||||
|
g.SetHighQuality();
|
||||||
|
GraphicsPath path = pts.Path();
|
||||||
|
g.FillPath(br, path);
|
||||||
|
g.DrawPath(pn, path);
|
||||||
|
path.Dispose();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UILinePointSymbol.Triangle:
|
||||||
|
{
|
||||||
|
PointF pt1 = new PointF(p.X, p.Y - series.SymbolSize);
|
||||||
|
PointF pt2 = new PointF(p.X - series.SymbolSize * 0.866f, p.Y + series.SymbolSize * 0.5f);
|
||||||
|
PointF pt3 = new PointF(p.X + series.SymbolSize * 0.866f, p.Y + series.SymbolSize * 0.5f);
|
||||||
|
PointF[] pts = { pt1, pt2, pt3, pt1 };
|
||||||
|
g.SetHighQuality();
|
||||||
|
GraphicsPath path = pts.Path();
|
||||||
|
g.FillPath(br, path);
|
||||||
|
g.DrawPath(pn, path);
|
||||||
|
path.Dispose();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UILinePointSymbol.Circle:
|
||||||
|
g.SetHighQuality();
|
||||||
|
g.FillEllipse(br, p.X - series.SymbolSize, p.Y - series.SymbolSize, series.SymbolSize * 2, series.SymbolSize * 2);
|
||||||
|
g.DrawEllipse(pn, p.X - series.SymbolSize, p.Y - series.SymbolSize, series.SymbolSize * 2, series.SymbolSize * 2);
|
||||||
|
break;
|
||||||
|
case UILinePointSymbol.Plus:
|
||||||
|
g.DrawLine(pn, p.X - series.SymbolSize, p.Y, p.X + series.SymbolSize, p.Y);
|
||||||
|
g.DrawLine(pn, p.X, p.Y - series.SymbolSize, p.X, p.Y + series.SymbolSize);
|
||||||
|
break;
|
||||||
|
case UILinePointSymbol.Star:
|
||||||
|
g.SetHighQuality();
|
||||||
|
g.DrawLine(pn, p.X, p.Y - series.SymbolSize, p.X, p.Y + series.SymbolSize);
|
||||||
|
g.DrawLine(pn, p.X - series.SymbolSize * 0.866f, p.Y + series.SymbolSize * 0.5f,
|
||||||
|
p.X + series.SymbolSize * 0.866f, p.Y - series.SymbolSize * 0.5f);
|
||||||
|
g.DrawLine(pn, p.X - series.SymbolSize * 0.866f, p.Y - series.SymbolSize * 0.5f,
|
||||||
|
p.X + series.SymbolSize * 0.866f, p.Y + series.SymbolSize * 0.5f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g.SetDefaultQuality();
|
||||||
|
}
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
@ -309,5 +410,67 @@ namespace Sunny.UI
|
|||||||
g.DrawString(line.Name, SubFont, line.Color, Width - sf.Width - 4 - LineOption.Grid.Right, pos - 2 - sf.Height);
|
g.DrawString(line.Name, SubFont, line.Color, Width - sf.Width - 4 - LineOption.Grid.Right, pos - 2 - sf.Height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly List<UILineSelectPoint> selectPoints = new List<UILineSelectPoint>();
|
||||||
|
private readonly List<UILineSelectPoint> selectPointsTemp = new List<UILineSelectPoint>();
|
||||||
|
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnMouseMove(e);
|
||||||
|
if (!NeedDraw) return;
|
||||||
|
|
||||||
|
selectPointsTemp.Clear();
|
||||||
|
foreach (var series in LineOption.Series.Values)
|
||||||
|
{
|
||||||
|
if (series.GetNearestPoint(e.Location, 4, out double x, out double y, out int index))
|
||||||
|
{
|
||||||
|
UILineSelectPoint point = new UILineSelectPoint();
|
||||||
|
point.Name = series.Name;
|
||||||
|
point.Index = index;
|
||||||
|
point.X = x;
|
||||||
|
point.Y = y;
|
||||||
|
selectPointsTemp.Add(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNew = false;
|
||||||
|
if (selectPointsTemp.Count != selectPoints.Count)
|
||||||
|
{
|
||||||
|
isNew = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, UILineSelectPoint> points = selectPoints.ToDictionary(p => p.Name);
|
||||||
|
foreach (var point in selectPointsTemp)
|
||||||
|
{
|
||||||
|
if (!points.ContainsKey(point.Name))
|
||||||
|
{
|
||||||
|
isNew = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points[point.Name].Index != point.Index)
|
||||||
|
{
|
||||||
|
isNew = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
{
|
||||||
|
selectPoints.Clear();
|
||||||
|
foreach (var point in selectPointsTemp)
|
||||||
|
{
|
||||||
|
selectPoints.Add(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointValue?.Invoke(this, selectPoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void OnPointValue(object sender, List<UILineSelectPoint> points);
|
||||||
|
|
||||||
|
public event OnPointValue PointValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
namespace Sunny.UI.Charts
|
namespace Sunny.UI
|
||||||
{
|
{
|
||||||
public sealed class UILineOption : UIOption, IDisposable
|
public sealed class UILineOption : UIOption, IDisposable
|
||||||
{
|
{
|
||||||
@ -29,10 +29,20 @@ namespace Sunny.UI.Charts
|
|||||||
public readonly List<UIScaleLine> XAxisScaleLines = new List<UIScaleLine>();
|
public readonly List<UIScaleLine> XAxisScaleLines = new List<UIScaleLine>();
|
||||||
|
|
||||||
public readonly List<UIScaleLine> YAxisScaleLines = new List<UIScaleLine>();
|
public readonly List<UIScaleLine> YAxisScaleLines = new List<UIScaleLine>();
|
||||||
public void AddSeries(UILineSeries series)
|
|
||||||
|
public UILineSeries AddSeries(UILineSeries series)
|
||||||
{
|
{
|
||||||
if (series.Name.IsNullOrEmpty()) return;
|
if (series.Name.IsNullOrEmpty()) return null;
|
||||||
Series.TryAdd(series.Name, series);
|
Series.TryAdd(series.Name, series);
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UILineSeries AddSeries(string name)
|
||||||
|
{
|
||||||
|
if (name.IsNullOrEmpty()) return null;
|
||||||
|
UILineSeries series = new UILineSeries(name);
|
||||||
|
Series.TryAdd(series.Name, series);
|
||||||
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddData(string name, double x, double y)
|
public void AddData(string name, double x, double y)
|
||||||
@ -150,11 +160,13 @@ namespace Sunny.UI.Charts
|
|||||||
{
|
{
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
|
|
||||||
public float Width { get; set; } = 1;
|
public float Width { get; set; } = 2;
|
||||||
public Color Color { get; set; }
|
public Color Color { get; set; }
|
||||||
|
|
||||||
public UILinePointSymbol Symbol { get; set; } = UILinePointSymbol.None;
|
public UILinePointSymbol Symbol { get; set; } = UILinePointSymbol.None;
|
||||||
public int SymbolSize { get; set; } = 1;
|
public int SymbolSize { get; set; } = 4;
|
||||||
|
|
||||||
|
public int SymbolLineWidth { get; set; } = 1;
|
||||||
|
|
||||||
public Color SymbolColor { get; set; }
|
public Color SymbolColor { get; set; }
|
||||||
|
|
||||||
@ -181,13 +193,47 @@ namespace Sunny.UI.Charts
|
|||||||
|
|
||||||
public readonly List<PointF> Points = new List<PointF>();
|
public readonly List<PointF> Points = new List<PointF>();
|
||||||
|
|
||||||
|
private readonly List<double> PointsX = new List<double>();
|
||||||
|
|
||||||
|
private readonly List<double> PointsY = new List<double>();
|
||||||
|
|
||||||
public int DataCount => XData.Count;
|
public int DataCount => XData.Count;
|
||||||
|
|
||||||
|
public bool GetNearestPoint(Point p, int offset, out double x, out double y, out int index)
|
||||||
|
{
|
||||||
|
index = PointsX.BinarySearchNearIndex(p.X);
|
||||||
|
if (p.X >= PointsX[index] - offset && p.X <= PointsX[index] + offset &&
|
||||||
|
p.Y >= PointsY[index] - offset && p.Y <= PointsY[index] + offset)
|
||||||
|
{
|
||||||
|
x = XData[index];
|
||||||
|
y = YData[index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
XData.Clear();
|
XData.Clear();
|
||||||
YData.Clear();
|
YData.Clear();
|
||||||
|
ClearPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearPoints()
|
||||||
|
{
|
||||||
Points.Clear();
|
Points.Clear();
|
||||||
|
PointsX.Clear();
|
||||||
|
PointsY.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPoint(PointF point)
|
||||||
|
{
|
||||||
|
Points.Add(point);
|
||||||
|
PointsX.Add(point.X);
|
||||||
|
PointsY.Add(point.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(double x, double y)
|
public void Add(double x, double y)
|
||||||
@ -221,4 +267,15 @@ namespace Sunny.UI.Charts
|
|||||||
Plus,
|
Plus,
|
||||||
Star
|
Star
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct UILineSelectPoint
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public double X { get; set; }
|
||||||
|
|
||||||
|
public double Y { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,67 @@ namespace Sunny.UI
|
|||||||
degree_end = end2;
|
degree_end = end2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算刻度
|
||||||
|
/// 起始值必须小于结束值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">起始值</param>
|
||||||
|
/// <param name="end">结束值</param>
|
||||||
|
/// <param name="expect_num">期望刻度数量,实际数接近此数</param>
|
||||||
|
/// <param name="degree_start">刻度起始值,须乘以间隔使用</param>
|
||||||
|
/// <param name="degree_end">刻度结束值,须乘以间隔使用</param>
|
||||||
|
/// <param name="degree_gap">刻度间隔</param>
|
||||||
|
public static void CalcDateTimeDegreeScale(double start, double end, int expect_num,
|
||||||
|
out int degree_start, out int degree_end, out double degree_gap)
|
||||||
|
{
|
||||||
|
if (start >= end)
|
||||||
|
{
|
||||||
|
throw new Exception("起始值必须小于结束值");
|
||||||
|
}
|
||||||
|
|
||||||
|
double differ = end - start;
|
||||||
|
double differ_gap = differ / (expect_num - 1); //35, 4.6, 0.27
|
||||||
|
|
||||||
|
double exponent = Math.Log10(differ_gap) - 1; //0.54, -0.34, -1.57
|
||||||
|
int _exponent = (int)exponent; //0, 0=>-1, -1=>-2
|
||||||
|
if (exponent < 0 && Math.Abs(exponent) > 1e-8)
|
||||||
|
{
|
||||||
|
_exponent--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int step = (int)(differ_gap / Math.Pow(10, _exponent)); //35, 46, 27
|
||||||
|
int[] fix_steps = new int[] { 10, 20, 30, 60, 120 };
|
||||||
|
int fix_step = 10; //25, 50, 25
|
||||||
|
for (int i = fix_steps.Length - 1; i >= 1; i--)
|
||||||
|
{
|
||||||
|
if (step > (fix_steps[i] + fix_steps[i - 1]) / 2)
|
||||||
|
{
|
||||||
|
fix_step = fix_steps[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
degree_gap = fix_step * Math.Pow(10, _exponent); //25, 5, 0.25
|
||||||
|
|
||||||
|
double start1 = start / degree_gap;
|
||||||
|
int start2 = (int)start1;
|
||||||
|
if (start1 < 0 && Math.Abs(start1 - start2) > 1e-8)
|
||||||
|
{
|
||||||
|
start2--;
|
||||||
|
}
|
||||||
|
|
||||||
|
degree_start = start2;
|
||||||
|
|
||||||
|
double end1 = end / degree_gap;
|
||||||
|
int end2 = (int)end1;
|
||||||
|
if (end1 >= 0 && Math.Abs(end1 - end2) > 1e-8)
|
||||||
|
{
|
||||||
|
end2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
degree_end = end2;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算刻度
|
/// 计算刻度
|
||||||
/// 起始值必须小于结束值
|
/// 起始值必须小于结束值
|
||||||
|
Loading…
x
Reference in New Issue
Block a user