313 lines
13 KiB
C#
313 lines
13 KiB
C#
using System;
|
||||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Drawing;
|
|||
|
|
using System.Drawing.Text;
|
|||
|
|
using System.Windows.Forms.DataVisualization.Charting;
|
|||
|
|
|
|||
|
|
namespace JinYuan.Helper
|
|||
|
|
{
|
|||
|
|
public class ChartHelper
|
|||
|
|
{
|
|||
|
|
// 字体缓存
|
|||
|
|
private static readonly Dictionary<string, Font> _fontCache = new Dictionary<string, Font>();
|
|||
|
|
private static PrivateFontCollection _fontCollection;
|
|||
|
|
private static readonly object _fontLock = new object();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化字体集合
|
|||
|
|
/// </summary>
|
|||
|
|
private static void InitializeFontCollection()
|
|||
|
|
{
|
|||
|
|
if (_fontCollection == null)
|
|||
|
|
{
|
|||
|
|
lock (_fontLock)
|
|||
|
|
{
|
|||
|
|
if (_fontCollection == null)
|
|||
|
|
{
|
|||
|
|
_fontCollection = new PrivateFontCollection();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 只加载一次字体文件
|
|||
|
|
string fontPath = Environment.CurrentDirectory + "\\Assts\\Fonts\\Zen圓体-Regular.ttf";
|
|||
|
|
if (System.IO.File.Exists(fontPath))
|
|||
|
|
{
|
|||
|
|
_fontCollection.AddFontFile(fontPath);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
// 字体加载失败,使用默认字体
|
|||
|
|
LogHelper.Instance.WriteError($"字体加载失败: {ex.Message}", "FontError");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取字体
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="size">字体大小</param>
|
|||
|
|
/// <param name="style">字体样式</param>
|
|||
|
|
/// <returns>字体对象</returns>
|
|||
|
|
private static Font GetFont(float size, FontStyle style)
|
|||
|
|
{
|
|||
|
|
string key = $"{size}_{style}";
|
|||
|
|
|
|||
|
|
if (_fontCache.TryGetValue(key, out Font cachedFont))
|
|||
|
|
{
|
|||
|
|
return cachedFont;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lock (_fontLock)
|
|||
|
|
{
|
|||
|
|
if (_fontCache.TryGetValue(key, out cachedFont))
|
|||
|
|
{
|
|||
|
|
return cachedFont;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
InitializeFontCollection();
|
|||
|
|
Font font;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (_fontCollection != null && _fontCollection.Families.Length > 0)
|
|||
|
|
{
|
|||
|
|
FontFamily fontFamily = new FontFamily(_fontCollection.Families[0].Name, _fontCollection);
|
|||
|
|
font = new Font(fontFamily, size, style);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 使用默认字体作为 fallback
|
|||
|
|
font = new Font("微软雅黑", size, style);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
// 字体创建失败,使用默认字体
|
|||
|
|
font = new Font("微软雅黑", size, style);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_fontCache[key] = font;
|
|||
|
|
return font;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 清理字体缓存
|
|||
|
|
/// </summary>
|
|||
|
|
public static void ClearFontCache()
|
|||
|
|
{
|
|||
|
|
lock (_fontLock)
|
|||
|
|
{
|
|||
|
|
foreach (var font in _fontCache.Values)
|
|||
|
|
{
|
|||
|
|
font.Dispose();
|
|||
|
|
}
|
|||
|
|
_fontCache.Clear();
|
|||
|
|
|
|||
|
|
if (_fontCollection != null)
|
|||
|
|
{
|
|||
|
|
_fontCollection.Dispose();
|
|||
|
|
_fontCollection = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name:添加序列
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chart">图表对象</param>
|
|||
|
|
/// <param name="seriesName">序列名称</param>
|
|||
|
|
/// <param name="chartType">图表类型</param>
|
|||
|
|
/// <param name="chartValueType">图表值类型</param>
|
|||
|
|
/// <param name="markerStyle">标记样式</param>
|
|||
|
|
/// <param name="markerSize">标记大小</param>
|
|||
|
|
/// <param name="seriesColor">颜色</param>
|
|||
|
|
/// <param name="markColor">标记点颜色</param>
|
|||
|
|
/// <param name="LabelStyle">标签样式</param>
|
|||
|
|
/// <param name="isShowBFH">是否显示百分比</param>
|
|||
|
|
/// <param name="showValue">是否显示数值</param>
|
|||
|
|
public static void AddSeries(Chart chart, string seriesName, SeriesChartType chartType, ChartValueType chartValueType, MarkerStyle markerStyle, int markerSize, Color seriesColor, Color markColor, string LabelStyle, bool isShowBFH, bool showValue = false)
|
|||
|
|
{
|
|||
|
|
chart.Series.Add(seriesName);
|
|||
|
|
chart.Series[seriesName].ChartType = chartType;
|
|||
|
|
chart.Series[seriesName].Color = seriesColor;
|
|||
|
|
if (showValue)
|
|||
|
|
{
|
|||
|
|
Font myFont = GetFont(9.0f, FontStyle.Bold);
|
|||
|
|
|
|||
|
|
chart.Series[seriesName].IsValueShownAsLabel = showValue;
|
|||
|
|
chart.Series[seriesName].XValueType = chartValueType;
|
|||
|
|
chart.Series[seriesName].Label = LabelStyle;
|
|||
|
|
chart.Series[seriesName].Font = myFont;
|
|||
|
|
chart.Series[seriesName].MarkerStyle = markerStyle;
|
|||
|
|
chart.Series[seriesName].MarkerColor = markColor;
|
|||
|
|
chart.Series[seriesName].MarkerStyle = MarkerStyle.Circle; //线条上的数据点标志类型
|
|||
|
|
chart.Series[seriesName].MarkerSize = markerSize; //标志大小
|
|||
|
|
chart.Series[seriesName].LabelToolTip = "#VALX: #VALY";
|
|||
|
|
chart.Series[seriesName].LabelForeColor = markColor;
|
|||
|
|
chart.Series[seriesName].LabelAngle = -75;
|
|||
|
|
chart.Series[seriesName].BorderWidth = 3;
|
|||
|
|
chart.Series[seriesName].LabelBorderWidth = 5;
|
|||
|
|
|
|||
|
|
if (isShowBFH)
|
|||
|
|
{
|
|||
|
|
chart.Series[seriesName].YAxisType = AxisType.Secondary;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name:设置标题
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chart">图表对象</param>
|
|||
|
|
/// <param name="chartName">图表名称</param>
|
|||
|
|
/// <param name="font">字体</param>
|
|||
|
|
/// <param name="docking">停靠位置</param>
|
|||
|
|
/// <param name="foreColor">前景色</param>
|
|||
|
|
public static void SetTitle(Chart chart, string chartName, Font font, Docking docking, Color foreColor)
|
|||
|
|
{
|
|||
|
|
chart.Titles.Add(chartName);
|
|||
|
|
chart.Titles[0].Font = font;
|
|||
|
|
chart.Titles[0].Docking = docking;
|
|||
|
|
chart.Titles[0].ForeColor = foreColor;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name:设置样式
|
|||
|
|
/// 2019-04-23 14:04
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chart">图表对象</param>
|
|||
|
|
/// <param name="backColor">背景颜色</param>
|
|||
|
|
/// <param name="foreColor">字体颜色</param>
|
|||
|
|
public static void SetStyle(Chart chart, Color backColor, Color foreColor)
|
|||
|
|
{
|
|||
|
|
chart.BackColor = backColor;
|
|||
|
|
chart.ChartAreas[0].BackColor = backColor;
|
|||
|
|
chart.ForeColor = Color.Red;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name:设置图例
|
|||
|
|
/// Author:
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chart">图表对象</param>
|
|||
|
|
/// <param name="docking">停靠位置</param>
|
|||
|
|
/// <param name="align">对齐方式</param>
|
|||
|
|
/// <param name="backColor">背景颜色</param>
|
|||
|
|
/// <param name="foreColor">字体颜色</param>
|
|||
|
|
public static void SetLegend(Chart chart, Docking docking, StringAlignment align, Color backColor, Color foreColor)
|
|||
|
|
{
|
|||
|
|
Font myFont = GetFont(9.0f, FontStyle.Regular);
|
|||
|
|
|
|||
|
|
chart.Legends[0].Docking = docking;
|
|||
|
|
chart.Legends[0].Alignment = align;
|
|||
|
|
chart.Legends[0].BackColor = backColor;
|
|||
|
|
chart.Legends[0].ForeColor = foreColor;
|
|||
|
|
chart.Legends[0].Font = myFont;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name:设置XY轴
|
|||
|
|
/// Author:
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chart">图表对象</param>
|
|||
|
|
/// <param name="xTitle">X轴标题</param>
|
|||
|
|
/// <param name="yTitle">Y轴标题</param>
|
|||
|
|
/// <param name="Angle">角度</param>
|
|||
|
|
/// <param name="align">坐标轴标题对齐方式</param>
|
|||
|
|
/// <param name="foreColor">坐标轴字体颜色</param>
|
|||
|
|
/// <param name="lineColor">坐标轴颜色</param>
|
|||
|
|
/// <param name="arrowStyle">坐标轴箭头样式</param>
|
|||
|
|
/// <param name="xInterval">X轴的间距</param>
|
|||
|
|
/// <param name="isShowBFH">是否显示百分比</param>
|
|||
|
|
/// <param name="isShowTime">是否显示时间</param>
|
|||
|
|
public static void SetXY(Chart chart, string xTitle, string yTitle, int Angle, StringAlignment align, Color foreColor, Color lineColor, AxisArrowStyle arrowStyle, double xInterval, bool isShowBFH, bool isShowTime = false)
|
|||
|
|
{
|
|||
|
|
Font myFont = GetFont(15f, FontStyle.Regular);
|
|||
|
|
|
|||
|
|
chart.ChartAreas[0].AxisX.TitleForeColor = foreColor;
|
|||
|
|
chart.ChartAreas[0].AxisX.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
|||
|
|
chart.ChartAreas[0].AxisX.LabelStyle.Angle = Angle;
|
|||
|
|
chart.ChartAreas[0].AxisX.LineColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisX.LabelStyle.ForeColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisX.ArrowStyle = arrowStyle;
|
|||
|
|
chart.ChartAreas[0].AxisX.Interval = xInterval;
|
|||
|
|
chart.ChartAreas[0].AxisX.Title = xTitle;
|
|||
|
|
chart.ChartAreas[0].AxisX.TitleAlignment = align;
|
|||
|
|
|
|||
|
|
chart.ChartAreas[0].AxisY.TitleForeColor = foreColor;
|
|||
|
|
chart.ChartAreas[0].AxisY.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
|||
|
|
chart.ChartAreas[0].AxisY.LineColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisY.LabelStyle.ForeColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisY.ArrowStyle = arrowStyle;
|
|||
|
|
chart.ChartAreas[0].AxisY.Title = yTitle;
|
|||
|
|
chart.ChartAreas[0].AxisY.TitleAlignment = align;
|
|||
|
|
|
|||
|
|
if (isShowBFH)
|
|||
|
|
{
|
|||
|
|
chart.ChartAreas[0].AxisY2.Minimum = 0;
|
|||
|
|
chart.ChartAreas[0].AxisY2.Maximum = 1.2;
|
|||
|
|
chart.ChartAreas[0].AxisY2.Interval = 0.2;
|
|||
|
|
chart.ChartAreas[0].AxisY2.LabelStyle = new LabelStyle() { ForeColor = foreColor };
|
|||
|
|
chart.ChartAreas[0].AxisY2.LineColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisY2.LabelStyle.ForeColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisY2.LabelStyle.Format = "0.00%";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
////设置图表显示样式
|
|||
|
|
if (isShowTime)
|
|||
|
|
{
|
|||
|
|
chart.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss"; //毫秒格式: hh:mm:ss.fff ,后面几个f则保留几位毫秒小数,此时要注意轴的最大值和最小值不要差太大
|
|||
|
|
chart.ChartAreas[0].AxisX.LabelStyle.IntervalType = DateTimeIntervalType.Seconds;
|
|||
|
|
chart.ChartAreas[0].AxisX.Interval = xInterval; //坐标值间隔1S
|
|||
|
|
chart.ChartAreas[0].AxisX.LabelStyle.IsEndLabelVisible = false; //防止X轴坐标跳跃
|
|||
|
|
chart.ChartAreas[0].AxisX.MajorGrid.IntervalType = DateTimeIntervalType.Seconds;
|
|||
|
|
|
|||
|
|
//chart.ChartAreas[0].AxisY.L = 1; //网格间隔
|
|||
|
|
|
|||
|
|
chart.ChartAreas[0].AxisX.Minimum = DateTime.Now.ToOADate(); //当前时间
|
|||
|
|
chart.ChartAreas[0].AxisX.Maximum = DateTime.Now.ToOADate();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Name:设置网格
|
|||
|
|
/// Author:
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="chart">图表对象</param>
|
|||
|
|
/// <param name="lineColor">网格线颜色</param>
|
|||
|
|
/// <param name="xInterval">X轴网格的间距</param>
|
|||
|
|
/// <param name="yInterval">Y轴网格的间距</param>
|
|||
|
|
/// <param name="isMajorGridX">是否显示X轴网格</param>
|
|||
|
|
/// <param name="isMajorGridY">是否显示Y轴网格</param>
|
|||
|
|
public static void SetMajorGrid(Chart chart, Color lineColor, double xInterval, double yInterval, bool isMajorGridX = false, bool isMajorGridY = false)
|
|||
|
|
{
|
|||
|
|
chart.ChartAreas[0].AxisX.MajorGrid.Enabled = isMajorGridX;
|
|||
|
|
chart.ChartAreas[0].AxisY.MajorGrid.Enabled = isMajorGridY;
|
|||
|
|
chart.ChartAreas[0].AxisY2.MajorGrid.Enabled = isMajorGridY;
|
|||
|
|
if (isMajorGridX)
|
|||
|
|
{
|
|||
|
|
chart.ChartAreas[0].AxisX.MajorGrid.LineColor = lineColor;
|
|||
|
|
|
|||
|
|
chart.ChartAreas[0].AxisX.MajorGrid.Interval = xInterval;
|
|||
|
|
|
|||
|
|
chart.ChartAreas[0].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isMajorGridY)
|
|||
|
|
{
|
|||
|
|
chart.ChartAreas[0].AxisY.MajorGrid.LineColor = lineColor;
|
|||
|
|
chart.ChartAreas[0].AxisY.MajorGrid.Interval = yInterval;
|
|||
|
|
chart.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|