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 _fontCache = new Dictionary(); private static PrivateFontCollection _fontCollection; private static readonly object _fontLock = new object(); /// /// 初始化字体集合 /// 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"); } } } } } /// /// 获取字体 /// /// 字体大小 /// 字体样式 /// 字体对象 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; } } /// /// 清理字体缓存 /// public static void ClearFontCache() { lock (_fontLock) { foreach (var font in _fontCache.Values) { font.Dispose(); } _fontCache.Clear(); if (_fontCollection != null) { _fontCollection.Dispose(); _fontCollection = null; } } } /// /// Name:添加序列 /// /// /// 图表对象 /// 序列名称 /// 图表类型 /// 图表值类型 /// 标记样式 /// 标记大小 /// 颜色 /// 标记点颜色 /// 标签样式 /// 是否显示百分比 /// 是否显示数值 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; } } } /// /// Name:设置标题 /// /// /// 图表对象 /// 图表名称 /// 字体 /// 停靠位置 /// 前景色 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; } /// /// Name:设置样式 /// 2019-04-23 14:04 /// /// 图表对象 /// 背景颜色 /// 字体颜色 public static void SetStyle(Chart chart, Color backColor, Color foreColor) { chart.BackColor = backColor; chart.ChartAreas[0].BackColor = backColor; chart.ForeColor = Color.Red; } /// /// Name:设置图例 /// Author: /// /// 图表对象 /// 停靠位置 /// 对齐方式 /// 背景颜色 /// 字体颜色 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; } /// /// Name:设置XY轴 /// Author: /// /// 图表对象 /// X轴标题 /// Y轴标题 /// 角度 /// 坐标轴标题对齐方式 /// 坐标轴字体颜色 /// 坐标轴颜色 /// 坐标轴箭头样式 /// X轴的间距 /// 是否显示百分比 /// 是否显示时间 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(); } } /// /// Name:设置网格 /// Author: /// /// 图表对象 /// 网格线颜色 /// X轴网格的间距 /// Y轴网格的间距 /// 是否显示X轴网格 /// 是否显示Y轴网格 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; } } } }