* 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.uiImageButton1 = new Sunny.UI.UIImageButton();
|
||||
this.uiLine1 = new Sunny.UI.UILine();
|
||||
this.uiLineChart1 = new Sunny.UI.UILineChart();
|
||||
this.LineChart = new Sunny.UI.UILineChart();
|
||||
this.PagePanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).BeginInit();
|
||||
@ -47,7 +47,7 @@
|
||||
this.PagePanel.Controls.Add(this.uiImageButton2);
|
||||
this.PagePanel.Controls.Add(this.uiImageButton1);
|
||||
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);
|
||||
//
|
||||
// uiSymbolButton1
|
||||
@ -62,6 +62,7 @@
|
||||
this.uiSymbolButton1.Symbol = 61952;
|
||||
this.uiSymbolButton1.TabIndex = 34;
|
||||
this.uiSymbolButton1.Text = "数据";
|
||||
this.uiSymbolButton1.Click += new System.EventHandler(this.uiSymbolButton1_Click);
|
||||
//
|
||||
// uiImageButton3
|
||||
//
|
||||
@ -113,18 +114,19 @@
|
||||
this.uiLine1.Text = "UIBarChart";
|
||||
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.uiLineChart1.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||
this.uiLineChart1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
|
||||
this.uiLineChart1.Location = new System.Drawing.Point(30, 48);
|
||||
this.uiLineChart1.MinimumSize = new System.Drawing.Size(1, 1);
|
||||
this.uiLineChart1.Name = "uiLineChart1";
|
||||
this.uiLineChart1.Option = null;
|
||||
this.uiLineChart1.Size = new System.Drawing.Size(670, 400);
|
||||
this.uiLineChart1.TabIndex = 35;
|
||||
this.uiLineChart1.Text = "uiLineChart1";
|
||||
this.LineChart.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
|
||||
this.LineChart.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||
this.LineChart.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
|
||||
this.LineChart.Location = new System.Drawing.Point(30, 48);
|
||||
this.LineChart.MinimumSize = new System.Drawing.Size(1, 1);
|
||||
this.LineChart.Name = "LineChart";
|
||||
this.LineChart.Option = null;
|
||||
this.LineChart.Size = new System.Drawing.Size(670, 400);
|
||||
this.LineChart.TabIndex = 35;
|
||||
this.LineChart.Text = "uiLineChart1";
|
||||
this.LineChart.PointValue += new Sunny.UI.UILineChart.OnPointValue(this.LineChart_PointValue);
|
||||
//
|
||||
// FLineChart
|
||||
//
|
||||
@ -149,6 +151,6 @@
|
||||
private UIImageButton uiImageButton2;
|
||||
private UIImageButton uiImageButton1;
|
||||
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
|
||||
{
|
||||
@ -6,5 +10,63 @@
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,10 +61,13 @@ namespace Sunny.UI
|
||||
double min = double.MaxValue;
|
||||
double max = double.MinValue;
|
||||
foreach (var series in BarOption.Series)
|
||||
{
|
||||
if (series.Data.Count > 0)
|
||||
{
|
||||
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) max = 0;
|
||||
|
@ -159,15 +159,31 @@ namespace Sunny.UI
|
||||
|
||||
public event DoFormatter Formatter;
|
||||
|
||||
public string GetLabel(double value, int index)
|
||||
public string GetLabel(double value, int index, UIAxisType axisType = UIAxisType.Value)
|
||||
{
|
||||
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>
|
||||
/// 小数位个数,Formatter不为空时以Formatter为准
|
||||
/// </summary>
|
||||
public int DecimalCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 日期格式化字符串,Formatter不为空时以Formatter为准
|
||||
/// </summary>
|
||||
public string DateTimeFormat { get; set; } = "HH:mm";
|
||||
}
|
||||
|
||||
public class UIAxisTick
|
||||
|
@ -1,9 +1,10 @@
|
||||
using Sunny.UI.Charts;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Sunny.UI
|
||||
{
|
||||
@ -42,13 +43,13 @@ namespace Sunny.UI
|
||||
|
||||
foreach (var series in LineOption.Series.Values)
|
||||
{
|
||||
series.Points.Clear();
|
||||
series.ClearPoints();
|
||||
|
||||
for (int i = 0; i < series.XData.Count; i++)
|
||||
{
|
||||
float x = (float)(series.XData[i] - XAxisStart) * 1.0f * DrawSize.Width / (XAxisEnd - XAxisStart);
|
||||
float y = (float)(series.YData[i] - YAxisStart) * 1.0f * DrawSize.Height / (YAxisEnd - YAxisStart);
|
||||
series.Points.Add(new PointF(DrawOrigin.X + x, DrawOrigin.Y - y));
|
||||
float x = (float)((series.XData[i] - XAxisStart * XAxisInterval) * 1.0f * DrawSize.Width / XAxisInterval / (XAxisEnd - XAxisStart));
|
||||
float y = (float)((series.YData[i] - YAxisStart * YAxisInterval) * 1.0f * DrawSize.Height / YAxisInterval / (YAxisEnd - YAxisStart));
|
||||
series.AddPoint(new PointF(DrawOrigin.X + x, DrawOrigin.Y - y));
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,10 +62,13 @@ namespace Sunny.UI
|
||||
double min = double.MaxValue;
|
||||
double max = double.MinValue;
|
||||
foreach (var series in LineOption.Series.Values)
|
||||
{
|
||||
if (series.DataCount > 0)
|
||||
{
|
||||
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) max = 0;
|
||||
@ -93,8 +97,8 @@ namespace Sunny.UI
|
||||
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) max = 0;
|
||||
if (min > 0 && max > 0 && !LineOption.XAxis.Scale && LineOption.XAxisType == UIAxisType.Value) min = 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.MinAuto) min = LineOption.XAxis.Min;
|
||||
|
||||
@ -104,14 +108,25 @@ namespace Sunny.UI
|
||||
min = 0;
|
||||
}
|
||||
|
||||
if (LineOption.XAxisType == UIAxisType.Value || LineOption.XAxisType == UIAxisType.Category)
|
||||
{
|
||||
UIChartHelper.CalcDegreeScale(min, max, LineOption.XAxis.SplitNumber,
|
||||
out int startX, out int endX, out double intervalX);
|
||||
|
||||
XAxisStart = startX;
|
||||
XAxisEnd = endX;
|
||||
XAxisInterval = intervalX;
|
||||
}
|
||||
|
||||
if (LineOption.XAxisType == UIAxisType.Time)
|
||||
{
|
||||
UIChartHelper.CalcDateTimeDegreeScale(min, max, LineOption.XAxis.SplitNumber,
|
||||
out int startX, out int endX, out double intervalX);
|
||||
XAxisStart = startX;
|
||||
XAxisEnd = endX;
|
||||
XAxisInterval = intervalX;
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
private UILineOption LineOption
|
||||
{
|
||||
@ -131,15 +146,31 @@ namespace Sunny.UI
|
||||
option.Title.Text = "SunnyUI";
|
||||
option.Title.SubText = "LineChart";
|
||||
|
||||
option.AddSeries(new UILineSeries("Line"));
|
||||
option.AddData("Line", 0, 1);
|
||||
option.AddData("Line", 1, 2);
|
||||
option.AddData("Line", 2, 3);
|
||||
option.AddData("Line", 3, 4);
|
||||
option.AddData("Line", 4, 3);
|
||||
option.AddData("Line", 5, 2);
|
||||
var series = option.AddSeries(new UILineSeries("Line1"));
|
||||
series.Add(0, 1.2);
|
||||
series.Add(1.1, 2.2);
|
||||
series.Add(2.2, 3.2);
|
||||
series.Add(3.3, 4.2);
|
||||
series.Add(4.4, 3.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 = "数值";
|
||||
|
||||
emptyOption = option;
|
||||
@ -204,7 +235,7 @@ namespace Sunny.UI
|
||||
float wmax = 0;
|
||||
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);
|
||||
wmax = Math.Max(wmax, sf.Width);
|
||||
g.DrawString(label, SubFont, ChartStyle.ForeColor, start - sf.Width / 2.0f,
|
||||
@ -277,10 +308,80 @@ namespace Sunny.UI
|
||||
Color color = series.Color;
|
||||
if (!series.CustomColor) color = ChartStyle.GetColor(idx);
|
||||
|
||||
using (Pen pen = new Pen(color, series.Width))
|
||||
{
|
||||
g.SetHighQuality();
|
||||
if (series.Smooth)
|
||||
g.DrawCurve(color, series.Points.ToArray(), true);
|
||||
g.DrawCurve(pen, series.Points.ToArray());
|
||||
else
|
||||
g.DrawLines(series.Color, series.Points.ToArray(), true);
|
||||
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++;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
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.Drawing;
|
||||
|
||||
namespace Sunny.UI.Charts
|
||||
namespace Sunny.UI
|
||||
{
|
||||
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> 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);
|
||||
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)
|
||||
@ -150,11 +160,13 @@ namespace Sunny.UI.Charts
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public float Width { get; set; } = 1;
|
||||
public float Width { get; set; } = 2;
|
||||
public Color Color { get; set; }
|
||||
|
||||
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; }
|
||||
|
||||
@ -181,13 +193,47 @@ namespace Sunny.UI.Charts
|
||||
|
||||
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 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()
|
||||
{
|
||||
XData.Clear();
|
||||
YData.Clear();
|
||||
ClearPoints();
|
||||
}
|
||||
|
||||
public void ClearPoints()
|
||||
{
|
||||
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)
|
||||
@ -221,4 +267,15 @@ namespace Sunny.UI.Charts
|
||||
Plus,
|
||||
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;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// 计算刻度
|
||||
/// 起始值必须小于结束值
|
||||
|
Loading…
x
Reference in New Issue
Block a user