chart 控件动态曲线 x轴时间ms显示,可滚动,添加边界线条

参考文档:

1、x轴怎么显示时间

c#chart 的x轴设置时间格式,第一个坐标从0开始_c# chart 坐标轴-优快云博客

2、动态曲线绘制(能局部放大)

C# winform 多个chart动态曲线绘制(能局部放大)_winform 曲线图表-优快云博客

3、当数据量较大时,x轴出现滚动条

C#中chart控件--(当数据量较大时,x轴出现滚动条)_winform chart x轴 毫秒级 滚动条-优快云博客

 4、添加边界线条

c# chart控件添加边界值线条以及扩展性功能 - AKA-Green - 博客园 (cnblogs.com)

结合以上参考 x轴设置为ms显示滚动条可以拖拽,支持放大缩小,支持最大值显示 

X轴类型设置

//间隔
            //chartArea.AxisY.Interval = 20;
            //chartArea.AxisY.Minimum = 0;
            //chartArea.AxisY.Maximum = 100;

            chartArea.AxisX.LabelStyle.Format = "yy-MM-dd\r\nHH:mm:ss.fff"; //横坐标格式
            chartArea.AxisX.IntervalType = DateTimeIntervalType.Milliseconds;//如果是时间类型的数据,间隔方式可以是秒、分、时
            //chartArea.AxisX.Minimum = dateTime.ToOADate();
            //chartArea.AxisX.Maximum = dateTime.AddMilliseconds(1000).ToOADate();
            chartArea.AxisX.Interval = DateTime.Parse("00:00:00.100").Millisecond;

特别注意 数据视图的设置否则鼠标无法拖动滚动轴

//数据视图
            chartArea.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;//启用X轴滚动条按钮
            chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Auto;
            chartArea.AxisX.ScaleView.MinSize = 100;
            chartArea.AxisX.ScaleView.MinSizeType = DateTimeIntervalType.Milliseconds;
            chartArea.AxisX.ScaleView.SmallScrollMinSize = 100;
            chartArea.AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Milliseconds;
            chartArea.AxisX.ScaleView.SmallScrollSize = 100;
            chartArea.AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Milliseconds;
            chartArea.AxisX.ScaleView.Zoomable = true;

其中的类型设置为ms,默认的话滚动轴的单位太大界面是ms显示就会出现无法拖动滚动轴的情况

要实现滚动条实时跟随曲线主要设置chart1.ChartAreas[0].AxisX.ScaleView.Position这个参数的值

一个页面最大显示多少个数据受chart1.ChartAreas[0].AxisX.ScaleView.Size,再结合间隔中设置的chartArea.AxisX.Interval = DateTime.Parse("00:00:00.100").Millisecond;参数就可以计算出一个页面显示几个数据了。

range = r.Next(1, 60);    //随机取数

                dateTime = dateTime.AddMilliseconds(100);
                series1.Points.AddXY(dateTime, 5 + range);   //设置series点

                chart1.ChartAreas[0].AxisX.ScaleView.Size = dateTime.AddMilliseconds(900).ToOADate() - dateTime.ToOADate();
                sum++;
                if (sum <= chart1.ChartAreas[0].AxisX.ScaleView.Size)
                    chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate();
                else
                    chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate() - chart1.ChartAreas[0].AxisX.ScaleView.Size;

总体代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using ToolTip = System.Windows.Forms.ToolTip;

namespace TemperDisplay
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            createSeries();
            CreateChart();
        }

        private void CreateChart()
        {
            ChartArea chartArea = chart1.ChartAreas[0];
            dateTime = DateTime.Now;

            //游标
            chartArea.CursorX.IsUserEnabled = true;
            chartArea.CursorX.IsUserSelectionEnabled = true;
            chartArea.CursorX.AutoScroll = true;
            chartArea.CursorX.SelectionColor = Color.SkyBlue;
            chartArea.CursorX.IntervalType = DateTimeIntervalType.Milliseconds;
            chartArea.CursorX.Interval = 1;
            chartArea.CursorX.AxisType = AxisType.Primary;

            //数据视图
            chartArea.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;//启用X轴滚动条按钮
            chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Auto;
            chartArea.AxisX.ScaleView.MinSize = 100;
            chartArea.AxisX.ScaleView.MinSizeType = DateTimeIntervalType.Milliseconds;
            chartArea.AxisX.ScaleView.SmallScrollMinSize = 100;
            chartArea.AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Milliseconds;
            chartArea.AxisX.ScaleView.SmallScrollSize = 100;
            chartArea.AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Milliseconds;
            chartArea.AxisX.ScaleView.Zoomable = true;

            //外观
            chartArea.BackColor = Color.AliceBlue;                      //背景色
            chartArea.BackSecondaryColor = Color.White;                 //渐变背景色
            chartArea.BackGradientStyle = GradientStyle.TopBottom;      //渐变方式
            chartArea.BackHatchStyle = ChartHatchStyle.None;            //背景阴影
            chartArea.BorderDashStyle = ChartDashStyle.NotSet;          //边框线样式
            chartArea.BorderWidth = 1;                                  //边框宽度
            chartArea.BorderColor = Color.Black;

            //分割线
            chartArea.AxisX.MajorGrid.Enabled = true;
            chartArea.AxisY.MajorGrid.Enabled = true;

            // Axis 标签
            chartArea.AxisY.Title = @"Value";
            chartArea.AxisY.LabelAutoFitMinFontSize = 5;
            
            
            chartArea.AxisX.Title = @"Time";
            chartArea.AxisX.IsLabelAutoFit = true;
            chartArea.AxisX.LabelAutoFitMinFontSize = 5;
            chartArea.AxisX.LabelStyle.Angle = 0;         //标签旋转角度 -90 --- 90
            chartArea.AxisX.LabelStyle.IsEndLabelVisible = true;        
            chartArea.AxisX.TextOrientation = TextOrientation.Auto;     //文本方向

            //间隔
            //chartArea.AxisY.Interval = 20;
            //chartArea.AxisY.Minimum = 0;
            //chartArea.AxisY.Maximum = 100;

            chartArea.AxisX.LabelStyle.Format = "yy-MM-dd\r\nHH:mm:ss.fff"; //横坐标格式
            chartArea.AxisX.IntervalType = DateTimeIntervalType.Milliseconds;//如果是时间类型的数据,间隔方式可以是秒、分、时
            //chartArea.AxisX.Minimum = dateTime.ToOADate();
            //chartArea.AxisX.Maximum = dateTime.AddMilliseconds(1000).ToOADate();
            chartArea.AxisX.Interval = DateTime.Parse("00:00:00.100").Millisecond;
            
            //外观
            chartArea.AxisY.LineWidth = 2;                 //数据表纵向边沿宽度
            chartArea.AxisY.LineColor = Color.Black;       //数据表纵向边沿颜色
            chartArea.AxisY.Enabled = AxisEnabled.True;

            chartArea.AxisX.LineWidth = 2;
            chartArea.AxisX.LineColor = Color.Black;
            chartArea.AxisX.Enabled = AxisEnabled.True;

            //辅助线条
            double max = 25;
            StripLine stripMax = new StripLine();
            stripMax.Text = string.Format("最大:{0:F}", max);//展示文本
            stripMax.BackColor = Color.FromArgb(208, 109, 106);//背景色
            stripMax.Interval = 0;//间隔
            stripMax.IntervalOffset = max;//偏移量
            stripMax.StripWidth = 0.001;//线宽
            stripMax.ForeColor = Color.Yellow;//前景色
            stripMax.TextAlignment = StringAlignment.Near;//文本对齐方式
            chartArea.AxisY.StripLines.Add(stripMax);//添加到ChartAreas中

            //图表区矩形位置
            //chartArea.Position.Height = 85;
            //chartArea.Position.Width = 85;
            //chartArea.Position.X = 5;
            //chartArea.Position.Y = 7;

            //渐变样式
            chart1.BackGradientStyle = GradientStyle.TopBottom;
            //图表的边框颜色、
            chart1.BorderlineColor = Color.FromArgb(26, 59, 105);
            //图表的边框线条样式
            chart1.BorderlineDashStyle = ChartDashStyle.Solid;
            //图表边框线条的宽度
            chart1.BorderlineWidth = 2;
            //图表边框的皮肤
            chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;

        }
        Series series1;

        private void createSeries()
        {
            //Series1
            series1 = chart1.Series[0];

            //Series1 style
            series1.ToolTip = "温度:#VALY{F1}\n时间:#VALX{HH-mm-dd.fff}";    //鼠标停留在数据点上,显示XY值

            series1.Name = "PT1000温度";
            series1.ChartType = SeriesChartType.Spline;  // type
            series1.BorderWidth = 2;                    //线条宽度
            series1.Color = Color.Red;                  //线条颜色
            series1.XValueType = ChartValueType.DateTime;   //显示时间
            series1.YValueType = ChartValueType.Auto;
            series1.IsValueShownAsLabel = true;         //显示数据值
            series1.LabelFormat = "F1";                 //显示数据格式
            series1.LabelForeColor = Color.Black;       //显示数据颜色
            series1.LabelBackColor = Color.AliceBlue;   //显示数据背景色

            //Marker
            series1.MarkerStyle = MarkerStyle.Square; //标签点样式
            series1.MarkerSize = 5;
            series1.MarkerColor = Color.Black;        //标签点颜色

            //图标图例
            //停靠
            chart1.Legends[0].Alignment = StringAlignment.Far;  //靠右
            chart1.Legends[0].Docking = Docking.Top;             //靠上
        }

        static int range = 0;
        Random r = new Random(6);

        int sum = 1;
        bool flag = false;
        DateTime dateTime;
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (flag)
                return;
            else
            {
              
                range = r.Next(1, 60);    //随机取数

                dateTime = dateTime.AddMilliseconds(100);
                series1.Points.AddXY(dateTime, 5 + range);   //设置series点

                chart1.ChartAreas[0].AxisX.ScaleView.Size = dateTime.AddMilliseconds(900).ToOADate() - dateTime.ToOADate();
                sum++;
                if (sum <= chart1.ChartAreas[0].AxisX.ScaleView.Size)
                    chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate();
                else
                    chart1.ChartAreas[0].AxisX.ScaleView.Position = dateTime.ToOADate() - chart1.ChartAreas[0].AxisX.ScaleView.Size;

                //series1.Points.AddXY(sum, 5 + range);
                //sum++;
                //if (comboBox1.SelectedItem.ToString() == "OverView")    //切换试图
                //{
                //    chart1.ChartAreas[0].AxisX.ScaleView.Position = 1;
                //    if (sum > 10)
                //    {
                //        double max = chart1.ChartAreas[0].AxisX.Maximum;
                //        max = (sum / 10 + 1) * 10;
                //        chart1.ChartAreas[0].AxisX.Interval = max / 10;
                //    }
                //    chart1.ChartAreas[0].AxisX.ScaleView.Size = sum * 1.1;
                //    //chart.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.None;//启用X轴滚动条按钮
                //}
                //if (comboBox1.SelectedItem.ToString() == "Follow")
                //{
                //    //chart1.ChartAreas[0].AxisX.Interval = 1D;
                //    chart1.ChartAreas[0].AxisX.ScaleView.Size = 10D;
                //    if (sum <= chart1.ChartAreas[0].AxisX.ScaleView.Size)
                //        chart1.ChartAreas[0].AxisX.ScaleView.Position = 1;
                //    else
                //        chart1.ChartAreas[0].AxisX.ScaleView.Position = sum - chart1.ChartAreas[0].AxisX.ScaleView.Size;
                //}
            }

        }


        private void button1_Click(object sender, EventArgs e)
        {
            if (button1.Text == "开始")
            {
                timer1.Start();
                button1.Text = "暂停";
            }
            else
            {
                timer1.Stop();
                button1.Text = "开始";
            }
        }

        private void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
        {
            //无数据时返回
            if (chart1.Series[0].Points.Count == 0)
                return;

            double start_position = 0.0;
            double end_position = 0.0;
            double myInterval = 0.0;
            start_position = e.NewSelectionStart;
            end_position = e.NewSelectionEnd;
            myInterval = Math.Abs(start_position - end_position);

            Console.WriteLine(start_position.ToString() + " "+ end_position.ToString() + " "+myInterval.ToString());

            //if (myInterval == 0.0)
            //    return;

            ////X轴视图起点
            //chart1.ChartAreas[0].AxisX.ScaleView.Position = Math.Min(start_position, end_position);
            ////X轴视图长度
            //chart1.ChartAreas[0].AxisX.ScaleView.Size = myInterval;
            ////X轴间隔
            //if (myInterval < dateTime.AddMilliseconds(900).ToOADate() - dateTime.ToOADate())
            //{
            //    chart1.ChartAreas[0].AxisX.Interval = 100;
            //}
            //else
            //{
            //    chart1.ChartAreas[0].AxisX.Interval = Math.Floor(myInterval / 10);
            //}
            //flag = true;
            //if (!comboBox1.Items.Contains("Zoom"))
            //{
            //    comboBox1.Items.Add("Zoom");
            //    comboBox1.SelectedItem = "Zoom";
            //}

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox1.SelectedItem.ToString() == "Zoom")
            {
                flag = true;
            }
            else if (comboBox1.SelectedItem.ToString() == "OverView" || comboBox1.SelectedItem.ToString() == "Follow")
            {
                comboBox1.Items.Remove("Zoom");
                flag = false;
            }

        }



        Point lastPoint = new Point();//上次点的坐标
        ToolTip tp = new ToolTip();//tooltip展示条
        //绘制竖线坐标
        Point p1 = new Point(0, 0);
        Point p2 = new Point(0, 0);
        /// <summary>
        /// 鼠标移动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chart1_MouseMove(object sender, MouseEventArgs e)
        {
            this.Refresh();//刷新chart,使用clear会使chart上的图形完全清空
            Pen pen = new Pen(Color.Yellow);
            Graphics g = chart1.CreateGraphics();
            string seriesInfo = ""; //tooltip文本
            if (e.Location != lastPoint)//如果在上次点的位置不进行操作,此处操作会引发chart控件的refresh操作造成界面闪烁
            {
                for (int y = 0; y <= chart1.Size.Height; y++)//线条范围进行碰撞检测
                {
                    HitTestResult result = chart1.HitTest(e.X, y);
                    if (result.ChartElementType == ChartElementType.DataPoint)
                    {
                        foreach (DataPoint dpp in result.Series.Points)//数据点默认样式 使用索引的方式修改偶尔会出现无法正常修改完
                        {
                            dpp.MarkerStyle = MarkerStyle.Diamond;
                            dpp.MarkerColor = Color.White;
                            dpp.MarkerSize = 5;
                        }
                        int i = result.PointIndex;
                        DataPoint dp = result.Series.Points[i];
                        dp.MarkerStyle = MarkerStyle.Star4;//捕获到数据点的样式
                        dp.MarkerColor = Color.Orange;
                        dp.MarkerSize = 15;
                        //获取数据点的相对坐标
                        p1 = new Point((int)chart1.ChartAreas[0].AxisX.ValueToPixelPosition(dp.XValue), 0);
                        p2 = new Point((int)chart1.ChartAreas[0].AxisX.ValueToPixelPosition(dp.XValue), chart1.Size.Height);
                        seriesInfo = string.Format("分项:{0}  时间:{1}  能耗值:{2}", result.Series.LegendText, DateTime.FromOADate(dp.XValue), dp.YValues[0]);
                        break;
                    }
                }
                tp.AutoPopDelay = 5000;//展示tooltip
                tp.ShowAlways = false;
                tp.IsBalloon = true;
                tp.SetToolTip(chart1, seriesInfo);
            }
            lastPoint = e.Location;//记录本次位置
            g.DrawLine(pen, p1, p2);//绘制竖线
        }
    }
}

设计界面

需要添加的事件

最终效果

放大效果

辅助线条未关联,可根据实际情况关联就行。

摸着石头过河,感谢其他博主提供的代码,开源万岁!

评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值