FlexChart scroll with the mouse instead of the scroll bar

Posted by: alex.corti on 24 April 2023, 12:05 am EST

    • Post Options:
    • Link

    Posted 24 April 2023, 12:05 am EST - Updated 24 April 2023, 12:10 am EST

    Good morning,

    I am using winform FlexChart to display data in a .NET core application.

    For zooming and moving on the chart now the end user uses the scrollbar (see attached file) and it works.

    What he would like (he does not like the current function) is to use the mouse for zooming and scrolling on the X and Y axes.

    I saw that it is possible to zoom with the mouse, so I implemented it like your example and it works.

    My questions are:

    • How can I implement zooming out (the end user does not want to use the zoom reset button)?
    • How can I implement scrolling the graph, with the mouse, without using the scrollbar?

    Thanks Alex

  • Posted 24 April 2023, 9:18 pm EST

    Hi,

    Thanks for reaching out to us with your query.

    1. You can Zoom-Out through a button click by setting AxisX/AxisY’s Min and Max property to default(same value when FlexChart loaded.)

      Or you can achieve this requirement through MouseWheel Up/Down. to ZoomIn/ZoomOut at a specific point(mouse cursor).
           private void FlexChart_ZoomOut(object sender, EventArgs e)
            {
                flexChart.AxisX.Min = _xInitMin;
                flexChart.AxisX.Max = _xInitMax;
                flexChart.AxisY.Min = _yInitMin;
                flexChart.AxisY.Max = _yInitMax;
            }
            private void FlexChart_MouseWheel(object sender, MouseEventArgs e)
            {
                if (e.Delta < 0)
                    _scaleX = _scaleY = 1.5;
                else
                    _scaleX = _scaleY = 0.5;
                PerformZoom(_scaleX, _scaleY, e.Location);
            }
            private void PerformZoom(double scaleX, double scaleY, System.Drawing.Point pointToZoomAt)
            {
                Axis axisX = flexChart.AxisX;
                Axis axisY = flexChart.AxisY;
                Point point = new Point(axisX.ConvertBack(pointToZoomAt.X), axisY.ConvertBack(pointToZoomAt.Y));
                double min = ((IAxis)axisX).GetMin();
                double max = ((IAxis)axisX).GetMax();
                double min2 = ((IAxis)axisY).GetMin();
                double max2 = ((IAxis)axisY).GetMax();
                double val = point.X + (max - point.X) * scaleX;
                double val2 = point.X - (point.X - min) * scaleX;
                double val3 = point.Y + (max2 - point.Y) * scaleY;
                double val4 = point.Y - (point.Y - min2) * scaleY;
                axisX.Min = Math.Max(val2, _xInitMin);
                axisX.Max = Math.Min(val, _xInitMax);
                axisY.Min = Math.Max(val4, _yInitMin);
                axisY.Max = Math.Min(val3, _yInitMax);
            }
    1. You can support panning in FlexChart via mouse, where you doesn’t need Scrollbar for panning:
            private System.Drawing.Point _start, _last, ptNaN = new System.Drawing.Point(-1,-1);
            private bool startPanning;
            public bool IsPanning { get; set; }
    
            private void OnFlexChartMouseMove(object sender, MouseEventArgs e)
            {
                if (startPanning == false || e.Button != MouseButtons.Left)
                {
                    if (IsPanning)
                        IsPanning = false;
                    return;
                }
    
                IsPanning = true; //Start the Pan operation
                _last = e.Location;
    
                var dataPoint = flexChart.PointToData(_start);  //Start
                var newDataPoint = flexChart.PointToData(_last); //End
                PerformPan(dataPoint, newDataPoint);
                _start = _last;
            }
    
            private void OnFlexChartMouseUp(object sender, MouseEventArgs e)
            {
                _start = _last = ptNaN;
                if (IsPanning)
                    startPanning = IsPanning = false;  //End Pan Operation
            }
    
            private void OnFlexChartMouseLeftButtonDown(object sender, MouseEventArgs e)
            {
                if(e.Button == MouseButtons.Left) 
                {
                    _start = e.Location;
                    startPanning = true;
                }
                
            }
    
            private void PerformPan(System.Drawing.PointF start, System.Drawing.PointF end)
            {
                double currentXMin = (flexChart.AxisX as C1.Chart.IAxis).GetMin();
                double currentXMax = (flexChart.AxisX as C1.Chart.IAxis).GetMax();
                double currentYMin = (flexChart.AxisY as C1.Chart.IAxis).GetMin();
                double currentYMax = (flexChart.AxisY as C1.Chart.IAxis).GetMax();
    
                var deltaX = (end.X - start.X);
                var deltaY = (end.Y - start.Y);
                flexChart.BeginUpdate();
                ////Pan along X-axis
                if (currentXMin - deltaX >= _xInitMin && currentXMax - deltaX <= _xInitMax)
                {
                    flexChart.AxisX.Min = Math.Max(currentXMin - deltaX, _xInitMin);
                    flexChart.AxisX.Max = Math.Min(currentXMax - deltaX, _xInitMax);
                }
                ////Pan along Y-axis
                if (currentYMin - deltaY >= _yInitMin && currentYMax - deltaY <= _yInitMax)
                {
                    flexChart.AxisY.Min = Math.Max(currentYMin - deltaY, _yInitMin);
                    flexChart.AxisY.Max = Math.Min(currentYMax - deltaY, _yInitMax);
                }
                flexChart.EndUpdate();
            }
    

    Please refer the attached sample for the same: FlexChartSample.zip

    Best Regards,

    Nitin

  • Posted 25 April 2023, 6:44 pm EST

    Good morning Nitin,

    I download your example, I will test it and I will give you a feedback

    Thanks

  • Posted 26 April 2023, 4:50 pm EST

    Hi,

    We will wait for your feedback. If this doesn’t meet your requirement then you can share more details about your requirement and we will try to provide a better solution for it.

    Just in case you have another requirement. Then you can ask out here or you can create another forum thread for it.

    Best Regards,

    Nitin

  • Posted 26 April 2023, 8:01 pm EST

    Hi Nitin,

    the example working perfectly. I changed it. Thanks for your help I reach the customer’s goal.

    Alex

  • Posted 27 April 2023, 4:08 am EST - Updated 27 April 2023, 4:13 am EST

    Hi Nitin,

    in this same example you provided, when any Animation is set to ON there is an annoying out of Axis chart drawing, which immediately disapeears, but when we have a lotta series, it disappears after some redrawing…

    Just set FlexChart’s AnymationSettings property to “All” and run!

    Can U also check this behaviour, please?

    Thanks

    Fabio

  • Posted 27 April 2023, 5:34 pm EST

    Hi Fabio,

    Thanks for your observation. We have replicated this behavior at our end. This seems like a bug. So, we have escalated it to the development team. Will get back to you once we have any update from them.[Internal Tracking Id - C1CHART-2236]

    Best Regards,

    Nitin

  • Posted 1 May 2023, 7:01 pm EST

    Good morning Nitin,

    I have a litte mulfunction when I zoom several times: the problem is randomic.

    The series disappear or is plot incorrectly: see attached files.

    The original plot (100% size is the initial file that i loaded serveral days ago)

  • Posted 1 May 2023, 7:01 pm EST - Updated 1 May 2023, 7:06 pm EST

  • Posted 1 May 2023, 8:20 pm EST

    Hi Nitin for making zoom i want to use this portion of code:

    https://www.grapecity.com/componentone/docs/win/online-flexchart/zoom.html

    And I comment all the pan rows that you write for me

        #region  "FlexChart Events for Zoom and Pan"
        /// <summary>
        /// Reset Zoom
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _fChart_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                //if (e.Button == MouseButtons.Left)
                {
    
                    _fChart.BeginUpdate();
    
                    // Restore default values for axis limits
                    //_fChart.AxisX.Min = Double.NaN;
                    //_fChart.AxisY.Min = Double.NaN;
                    //_fChart.AxisX.Max = Double.NaN;
                    //_fChart.AxisY.Max = Double.NaN;
                    _fChart.AxisX.Min = _xInitMin;
                    _fChart.AxisX.Max = _xInitMax;
                    _fChart.AxisY.Min = _yInitMin;
                    _fChart.AxisY.Max = _yInitMax;
                    _maxZoomX = "";
                    _minZoomX = "";
                    _chartZoomIsActive = false;
                    _fChart.EndUpdate();
                }
            }
            catch (Exception ex)
            {
                ctrlLogger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                ctrlLogger.Error(ex.Message + "\n" + ex.StackTrace);
                if (ex.InnerException != null)
                    ctrlLogger.Error("Inner exception: " + ex.InnerException.Message);
            }
        }
        /// <summary>
        /// Update Range values on graph
        /// </summary>
        /// <param name="minX">Min X value</param>
        /// <param name="maxX">Max X value</param>
        /// <param name="minAxisY">Min Y value</param>
        /// <param name="maxAxisY">Max X value</param>
        private void UpdatedZoomRangeValues(string minX, string maxX, double minAxisY, double maxAxisY)
        {
            //double minAxisX, double maxAxisX,
            //string lbl_MinX = DateTime.FromOADate(minAxisX).ToString("yyyy-MM-dd hh:mm:ss");//minAxisX.ToString("N2");
            //string lbl_MaxX = DateTime.FromOADate(maxAxisX).ToString("yyyy-MM-dd hh:mm:ss");//maxAxisX.ToString("N2");
            _minZoomX = minX;
            _maxZoomX = maxX;
            string lbl_MinY = minAxisY.ToString("N2");
            string lbl_MaxY = maxAxisY.ToString("N2");
        }
        /// <summary>
        /// Mouse Up => Zoom or Pan
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _fChart_MouseUp(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left) // zoom
                {
                    // Stop Zooming
                    _IsMouseDown = false;
                    if (!_lastPoint.IsEmpty)
                    {
                        var start = _fChart.PointToData(_startPoint);
                        var last = _fChart.PointToData(_lastPoint);
                        float XMin = Math.Min(start.X, last.X);
                        float XMax = Math.Max(start.X, last.X);
                        float YMin = Math.Min(start.Y, last.Y);
                        float YMax = Math.Max(start.Y, last.Y);
                        //var max = (int)Math.Floor(XMax);
                        //var min = (int)Math.Ceiling(XMin);
    
                        //if (XMin >= XMax)
                        //{
                        //    _startPoint = _lastPoint = Point.Empty;.
                        //    _chartZoomIsActive = true;
                        //    return;
                        //}
                        //if (YMin >= YMax)
                        //{
                        //    _startPoint = _lastPoint = Point.Empty;
                        //    _chartZoomIsActive = true;
                        //    return;
                        //}
                        //_fChart.BeginUpdate();
                        //Update axes with new limits
                        //if (max > min +1)
                        //{
    
                        //}
                        _fChart.AxisX.Min = XMin;
                        _fChart.AxisX.Max = XMax;
    
                        _fChart.AxisY.Min = YMin;
                        _fChart.AxisY.Max = YMax;
    
                        //lblDebug.Text = "x = (" + _fChart.AxisX.Min.ToString() + ";" + _fChart.AxisX.Max.ToString() + ") - y = (" + _fChart.AxisY.Min.ToString() + ";" + _fChart.AxisY.Max.ToString() + ") ; min = " + min.ToString() + " ;  max = " + max.ToString();
    
                        //if (_fChart.DataSource is DataTable ds)
                        //{
    
                        //    //get the objects from DataSource with the help of Data points
                        //    UpdatedZoomRangeValues(ds.Rows[min][0].ToString(), ds.Rows[max][0].ToString(), _fChart.AxisY.Min, _fChart.AxisY.Max);
                        //    //pdateLabels(ds[min].Date, ds[max].Date, flexChart1.AxisY.Min, flexChart1.AxisY.Max);
                        //}
    
                        //if (pnlAvgTable.Visible == true) InitializeAvgPanel();
                        //_chartZoomIsActive = true;
                        _fChart.EndUpdate();
                    }
                    // Clean up
                    _startPoint = _lastPoint = Point.Empty;
                }
                //if (e.Button == System.Windows.Forms.MouseButtons.Right) //pan
                //{
                //    // Start panning
                //    _startPoint = _lastPoint = new System.Drawing.Point(-1, -1);
                //    if (_IsPanning)
                //        _startPanning = _IsPanning = false;  //End Pan Operation
                //}
    
    
            }
            catch (Exception ex)
            {
                ctrlLogger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                ctrlLogger.Error(ex.Message + "\n" + ex.StackTrace);
                if (ex.InnerException != null)
                    ctrlLogger.Error("Inner exception: " + ex.InnerException.Message);
            }
        }
    
        /// <summary>
        /// Mouse Move on Chart
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _fChart_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                //Drawing zoom region rectangle borders and update selection range
                if (_IsMouseDown && e.Button == MouseButtons.Left)
                {
                    var ptCurrent = e.Location;
                    var left = (int)_fChart.PlotRect.Left;
                    var right = (int)_fChart.PlotRect.Right;
                    var top = (int)_fChart.PlotRect.Top;
                    var bot = (int)_fChart.PlotRect.Bottom;
    
                    //Making sure that rectangle's end coordinate lies within FlexChart's PlotRect
                    ptCurrent.X = ptCurrent.X < left ? left : ptCurrent.X > right ? right : ptCurrent.X;
                    ptCurrent.Y = ptCurrent.Y < top ? top : ptCurrent.Y > bot ? bot : ptCurrent.Y;
                    _lastPoint = ptCurrent;
                    _fChart.Refresh();
                }
    
                //if (e.Button == MouseButtons.Right) // Pan
                //{
                //    if (_startPanning == false)
                //    {
                //        if (_IsPanning)
                //            _IsPanning = false;
                //        return;
                //    }
    
                //    _IsPanning = true; //Start the Pan operation
                //    _lastPoint = e.Location;
    
                //    var dataPoint = _fChart.PointToData(_startPoint);  //Start
                //    var newDataPoint = _fChart.PointToData(_lastPoint); //End
                //    PerformPan(dataPoint, newDataPoint);
                //    _startPoint = _lastPoint;
                //}
    
            }
            catch (Exception ex)
            {
                ctrlLogger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                ctrlLogger.Error(ex.Message + "\n" + ex.StackTrace);
                if (ex.InnerException != null)
                    ctrlLogger.Error("Inner exception: " + ex.InnerException.Message);
            }
    
        }
        /// <summary>
        /// Mouse Down => Zoom or Pan
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _fChart_MouseDown(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    //Start Zooming
                    _IsMouseDown = true;
                    _startPoint = e.Location;
                    _lastPoint = Point.Empty;
                }
                //if (e.Button == System.Windows.Forms.MouseButtons.Right)
                //{
                //    // Start panning
                //    _startPoint = e.Location;
                //    _startPanning = true;
                //}
            }
            catch (Exception ex)
            {
                ctrlLogger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                ctrlLogger.Error(ex.Message + "\n" + ex.StackTrace);
                if (ex.InnerException != null)
                    ctrlLogger.Error("Inner exception: " + ex.InnerException.Message);
            }
        }
        /// <summary>
        /// Render
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _fChart_Rendered(object sender, RenderEventArgs e)
        {
            if (!_startPoint.IsEmpty && !_lastPoint.IsEmpty)
            {
                // draw selection
                var p1 = _startPoint;
                var p2 = _lastPoint;
                e.Engine.SetFill(null);
                e.Engine.SetStroke(Brushes.Red);
                e.Engine.SetStrokeThickness(1);
                e.Engine.SetStrokePattern(new double[] { 3, 3 });
                e.Engine.DrawRect(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y), Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y));
            }
            //if (_IsLoading)
            //{
            //    Axis axisX = _fChart.AxisX;
            //    Axis axisY = _fChart.AxisY;
            //    _xInitMin = ((IAxis)axisX).GetMin();
            //    _xInitMax = ((IAxis)axisX).GetMax();
            //    _yInitMin = ((IAxis)axisY).GetMin();
            //    _yInitMax = ((IAxis)axisY).GetMax();
            //    _IsLoading = false;
            //}
        }
        /// <summary>
        /// Pan
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        private void PerformPan(System.Drawing.PointF start, System.Drawing.PointF end)
        {
            double currentXMin = (_fChart.AxisX as C1.Chart.IAxis).GetMin();
            double currentXMax = (_fChart.AxisX as C1.Chart.IAxis).GetMax();
            double currentYMin = (_fChart.AxisY as C1.Chart.IAxis).GetMin();
            double currentYMax = (_fChart.AxisY as C1.Chart.IAxis).GetMax();
    
            var deltaX = (end.X - start.X);
            var deltaY = (end.Y - start.Y);
            _fChart.BeginUpdate();
            ////Pan along X-axis
            if (currentXMin - deltaX >= _xInitMin && currentXMax - deltaX <= _xInitMax)
            {
                _fChart.AxisX.Min = Math.Max(currentXMin - deltaX, _xInitMin);
                _fChart.AxisX.Max = Math.Min(currentXMax - deltaX, _xInitMax);
            }
            ////Pan along Y-axis
            if (currentYMin - deltaY >= _yInitMin && currentYMax - deltaY <= _yInitMax)
            {
                _fChart.AxisY.Min = Math.Max(currentYMin - deltaY, _yInitMin);
                _fChart.AxisY.Max = Math.Min(currentYMax - deltaY, _yInitMax);
            }
            _fChart.EndUpdate();
        }
        #endregion
    
  • Posted 2 May 2023, 12:08 am EST - Updated 2 May 2023, 12:13 am EST

    I have the same problem with the standard example after 7 zoom on the chart (see attached files)

    So I think is not my application problem but it’s generic problem with the code that Componentone gives as zoom example

    Alex

  • Posted 2 May 2023, 11:15 pm EST

    Hi Alex,

    Thanks for your observation.

    We have replicated this behavior at our end. This seems like a bug. So, we have escalated this issue to the development team. Will gat back to you once we have any update from them.[Internal Tracking Id - C1CHART-2238]

    Best Regards,

    Nitin

  • Posted 4 May 2023, 6:02 pm EST

    Hi Alex,

    As per the development team, The problem only arises with spline chart. It’s because spline coefficients don’t have enough precision to calculated correct coordinates at large scale. We will try to address the problem in 2023v2 release.

    It’s possible, though, that you run into the different precision problem which isn’t specific for spline. You cannot zoom infinitely because the numeric values has limited precision (chart internally works with double’s) and at some scale it will not be enough to provide correct coordinate calculations. It shouldn’t be a problem for the most of real world applications since zooming in a such huge range are very rarely needed. We would suggest to set some reasonable limit for zooming which is suitable for specific case.

    Best regards,

    Nitin

  • Posted 2 August 2023, 3:48 pm EST

    Hi,

    We are happy to inform you that the issue is fixed in 2023v2 version. You can download the 2023v2 installer from here: https://www.grapecity.com/componentone/download.

    Now the Symbol and line don’t have a gap after zooming.

    Best Regards,

    Nitin

  • Posted 2 August 2023, 6:17 pm EST

    Hi Nitin, thanks for the info I will download it and use it

    have a nice day

    Alex

  • Posted 26 September 2023, 3:45 pm EST

    Hi Fabio,

    The issue[C1CHART-2236], regarding the series drawn out of the axis on Zoom with Animation. This issue is fixed in the latest 2023v2 hotfix version.

    You can download the latest 2023v2 hotfix verion from ComponentOne Control Panel. If you don’t have the latest version of C1 Control Panel, then you can download it from here: https://www.grapecity.com/componentone/download

    Regards,

    Nitin

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels