ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  xAxis and YAxis panning
Posted by abhishek B L on Apr-13-2022 20:24
Attachments:
I need an sample code for Xaxis and Yaxis panning for Axischart
Graph1.PNG

  Re: xAxis and YAxis panning
Posted by Peter Kwan on Apr-14-2022 01:51
Hi Abhishek,

The followings are examples included in the ChartDirector distribution that can pan in both the x and y directions:

https://www.advsofteng.com/doc/cdnet.htm#xyzoomscroll.htm

In the simplest case, you just need to configure zoom and scroll direction of the the chart viewer control to both horizontal and vertical, and add code to synchronize the y-axis with viewport using "syncLinearAxisWithViewPort".

The exact details depending on your programming language, and whether you are writing a web or desktop application. If you need more specific tails, please inform me your programming language and application type. If it is a desktop application, please let me know the GUI framework you are using (eg, C++/MFC, C++/Qt, C#/WPF, VB/Windows Forms, etc).

Best Regards
Peter Kwan

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-14-2022 13:09
Programing langugae=c#(.net framework 3.5) for desktop application
Gui framework=wpf(.net .net framework 3.5)

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-14-2022 14:59
hi peter,

i am able do panning on Xaxis but panning is not working for yAxis,and i have set that zoom and scroll direction to bi-Direction still not able to do panning on y axis, can u help me out with this please

  Re: xAxis and YAxis panning
Posted by Peter Kwan on Apr-15-2022 03:32
Attachments:
Hi abhishek,

I have just modified the following sample code to make it zoom/scroll both horizontally and vertically.

https://www.advsofteng.com/doc/cdnet.htm#zoomscrolltrack.htm

I only added two lines. One is in the initChartViewer, and it sets the zoom and scroll directions:

viewer.ZoomDirection = viewer.ScrollDirection = WinChartDirection.HorizontalVertical;

The other is in the drawChart code, and it synchronizes the y-axis with the viewport.

viewer.syncLinearAxisWithViewPort("y", c.yAxis());

When you use the mouse wheel the zoom in, it will zoom in both the x and y directions, and you can drag the chart in both directions.

Regards
Peter Kwan
ZoomScrollTrackWindow.xaml
ZoomScrollTrackWindow.xaml

2.62 Kb
    
ZoomScrollTrackWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.IO;
using ChartDirector;

namespace CSharpWPFCharts
{
    /// <summary>
    /// Interaction logic for ZoomScrollTrack.xaml
    /// </summary>
    public partial class ZoomScrollTrackWindow : Window
    {
        // Data arrays
        private DateTime[] timeStamps;
        private double[] dataSeriesA;
        private double[] dataSeriesB;
        private double[] dataSeriesC;

        public ZoomScrollTrackWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Load the data
            loadData();

            // Initialize the WinChartViewer
            initChartViewer(WPFChartViewer1);

            // Trigger the ViewPortChanged event to draw the chart
            WPFChartViewer1.updateViewPort(true, true);
        }

        //
        // Load the data
        //
        private void loadData()
        {
            // In this example, we just use random numbers as data.
            RanSeries r = new RanSeries(127);
            timeStamps = r.getDateSeries(1827, new DateTime(2007, 1, 1), 86400);
            dataSeriesA = r.getSeries2(1827, 150, -10, 10);
            dataSeriesB = r.getSeries2(1827, 200, -10, 10);
            dataSeriesC = r.getSeries2(1827, 250, -8, 8);
        }

        //
        // Initialize the WinChartViewer
        //
        private void initChartViewer(WPFChartViewer viewer)
        {
            // Set the full x range to be the duration of the data
            viewer.setFullRange("x", timeStamps[0], timeStamps[timeStamps.Length - 1]);
            viewer.ZoomDirection = viewer.ScrollDirection = WinChartDirection.HorizontalVertical;

            // Enable mouse wheel zooming by setting the zoom ratio to 1.1 per wheel event
            viewer.MouseWheelZoomRatio = 1.1;

            // Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
            pointerPB.IsChecked = true;
        }

        //
        // The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in
        // or out the chart by dragging or clicking on the chart. It can also be triggered by
        // calling WinChartViewer.updateViewPort.
        //
        private void WPFChartViewer1_ViewPortChanged(object sender, WPFViewPortEventArgs e)
        {
            var viewer = sender as WPFChartViewer;

            // In addition to updating the chart, we may also need to update other controls that
            // changes based on the view port.
            updateControls(viewer);

            // Update the chart if necessary
            if (e.NeedUpdateChart)
                drawChart(viewer);
        }

        //
        // Update controls when the view port changed
        //
        private void updateControls(WPFChartViewer viewer)
        {
            // In this demo, we need to update the scroll bar to reflect the view port position and
            // width of the view port.
            hScrollBar1.IsEnabled = viewer.ViewPortWidth < 1;
            hScrollBar1.LargeChange = viewer.ViewPortWidth * (hScrollBar1.Maximum - hScrollBar1.Minimum);
            hScrollBar1.SmallChange = hScrollBar1.LargeChange * 0.1;
            hScrollBar1.ViewportSize = viewer.ViewPortWidth / Math.Max(1E-10, 1 - viewer.ViewPortWidth)
                * (hScrollBar1.Maximum - hScrollBar1.Minimum);
            hScrollBar1.Value = viewer.ViewPortLeft / Math.Max(1E-10, 1 - viewer.ViewPortWidth)
                * (hScrollBar1.Maximum - hScrollBar1.Minimum) + hScrollBar1.Minimum;
        }

        //
        // Draw the chart.
        //
        private void drawChart(WPFChartViewer viewer)
        {
            // Get the start date and end date that are visible on the chart.
            DateTime viewPortStartDate = Chart.NTime(viewer.getValueAtViewPort("x", viewer.ViewPortLeft));
            DateTime viewPortEndDate = Chart.NTime(viewer.getValueAtViewPort("x", viewer.ViewPortLeft +
                viewer.ViewPortWidth));

            // Get the array indexes that corresponds to the visible start and end dates
            int startIndex = (int)Math.Floor(Chart.bSearch(timeStamps, viewPortStartDate));
            int endIndex = (int)Math.Ceiling(Chart.bSearch(timeStamps, viewPortEndDate));
            int noOfPoints = endIndex - startIndex + 1;

            // Extract the part of the data array that are visible.
            DateTime[] viewPortTimeStamps = (DateTime[])Chart.arraySlice(timeStamps, startIndex, noOfPoints);
            double[] viewPortDataSeriesA = (double[])Chart.arraySlice(dataSeriesA, startIndex, noOfPoints);
            double[] viewPortDataSeriesB = (double[])Chart.arraySlice(dataSeriesB, startIndex, noOfPoints);
            double[] viewPortDataSeriesC = (double[])Chart.arraySlice(dataSeriesC, startIndex, noOfPoints);

            //
            // At this stage, we have extracted the visible data. We can use those data to plot the chart.
            //

            //================================================================================
            // Configure overall chart appearance.
            //================================================================================

            // Create an XYChart object of size 640 x 350 pixels
            XYChart c = new XYChart(640, 350);

            // Set the plotarea at (55, 55) with width 80 pixels less than chart width, and height 90 pixels
            // less than chart height. Use a vertical gradient from light blue (f0f6ff) to sky blue (a0c0ff)
            // as background. Set border to transparent and grid lines to white (ffffff).
            c.setPlotArea(55, 55, c.getWidth() - 80, c.getHeight() - 90, c.linearGradientColor(0, 55, 0,
                c.getHeight() - 35, 0xf0f6ff, 0xa0c0ff), -1, Chart.Transparent, 0xffffff, 0xffffff);

            // As the data can lie outside the plotarea in a zoomed chart, we need enable clipping.
            c.setClipping();

            // Add a title to the chart using 18 pts Times New Roman Bold Italic font
            c.addTitle("   Zooming and Scrolling with Track Line (1)", "Times New Roman Bold Italic", 18);

            // Set legend icon style to use line style icon, sized for 8pt font
            c.getLegend().setLineStyleKey();
            c.getLegend().setFontSize(8);

            // Set the axis stem to transparent
            c.xAxis().setColors(Chart.Transparent);
            c.yAxis().setColors(Chart.Transparent);

            // Add axis title using 10pts Arial Bold Italic font
            c.yAxis().setTitle("Ionic Temperature (C)", "Arial Bold Italic", 10);

            //================================================================================
            // Add data to chart
            //================================================================================

            //
            // In this example, we represent the data by lines. You may modify the code below to use other
            // representations (areas, scatter plot, etc).
            //

            // Add a line layer for the lines, using a line width of 2 pixels
            LineLayer layer = c.addLineLayer2();
            layer.setLineWidth(2);

            // In this demo, we do not have too many data points. In real code, the chart may contain a lot
            // of data points when fully zoomed out - much more than the number of horizontal pixels in this
            // plot area. So it is a good idea to use fast line mode.
            layer.setFastLineMode();

            // Now we add the 3 data series to a line layer, using the color red (ff33333), green (008800)
            // and blue (3333cc)
            layer.setXData(viewPortTimeStamps);
            layer.addDataSet(viewPortDataSeriesA, 0xff3333, "Alpha");
            layer.addDataSet(viewPortDataSeriesB, 0x008800, "Beta");
            layer.addDataSet(viewPortDataSeriesC, 0x3333cc, "Gamma");

            //================================================================================
            // Configure axis scale and labelling
            //================================================================================

            // Set the x-axis as a date/time axis with the scale according to the view port x range.
            viewer.syncDateAxisWithViewPort("x", c.xAxis());
            viewer.syncLinearAxisWithViewPort("y", c.yAxis());

            //
            // In this demo, the time range can be from a few years to a few days. We demonstrate how to set
            // up different date/time format based on the time range.
            //

            // If all ticks are yearly aligned, then we use "yyyy" as the label format.
            c.xAxis().setFormatCondition("align", 360 * 86400);
            c.xAxis().setLabelFormat("{value|yyyy}");

            // If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first label of a
            // year, and "mmm" for other labels.
            c.xAxis().setFormatCondition("align", 30 * 86400);
            c.xAxis().setMultiFormat(Chart.StartOfYearFilter(), "<*font=bold*>{value|mmm yyyy}",
                Chart.AllPassFilter(), "{value|mmm}");

            // If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the first
            // label of a year, and "mmm dd" in bold font as the first label of a month, and "dd" for other
            // labels.
            c.xAxis().setFormatCondition("align", 86400);
            c.xAxis().setMultiFormat(Chart.StartOfYearFilter(),
                "<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", Chart.StartOfMonthFilter(),
                "<*font=bold*>{value|mmm dd}");
            c.xAxis().setMultiFormat2(Chart.AllPassFilter(), "{value|dd}");

            // For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
            // and "hh:nn" for other labels.
            c.xAxis().setFormatCondition("else");
            c.xAxis().setMultiFormat(Chart.StartOfDayFilter(), "<*font=bold*>{value|hh:nn<*br*>mmm dd}",
                Chart.AllPassFilter(), "{value|hh:nn}");

            //================================================================================
            // Output the chart
            //================================================================================

            // We need to update the track line too. If the mouse is moving on the chart (eg. if 
            // the user drags the mouse on the chart to scroll it), the track line will be updated
            // in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
            if (!viewer.IsInMouseMoveEvent)
            {
                trackLineLegend(c, (null == viewer.Chart) ? c.getPlotArea().getRightX() :
                    viewer.PlotAreaMouseX);
            }

            viewer.Chart = c;
        }

        //
        // Pointer (Drag to Scroll) button event handler
        //
        private void pointerPB_Checked(object sender, RoutedEventArgs e)
        {
            WPFChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag;
        }

        //
        // Zoom In button event handler
        //
        private void zoomInPB_Checked(object sender, RoutedEventArgs e)
        {
            WPFChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn;
        }

        //
        // Zoom Out button event handler
        //
        private void zoomOutPB_Checked(object sender, RoutedEventArgs e)
        {
            WPFChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut;
        }

        //
        // The scroll bar event handler
        //
        private void hScrollBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            var viewer = WPFChartViewer1;

            // When the view port is changed (user drags on the chart to scroll), the scroll bar will get
            // updated. When the scroll bar changes (eg. user drags on the scroll bar), the view port will
            // get updated. This creates an infinite loop. To avoid this, the scroll bar can update the 
            // view port only if the view port is not updating the scroll bar.
            if (!viewer.IsInViewPortChangedEvent)
            {
                // Set the view port based on the scroll bar
                viewer.ViewPortLeft = (hScrollBar1.Value - hScrollBar1.Minimum) 
                    / (hScrollBar1.Maximum - hScrollBar1.Minimum) * (1 - viewer.ViewPortWidth);

                // Trigger a view port changed event to update the chart
                viewer.updateViewPort(true, false);
            }
        }

        //
        // Draw track cursor when mouse is moving over plotarea
        //
        private void WPFChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
        {
            var viewer = sender as WPFChartViewer;
            trackLineLegend((XYChart)viewer.Chart, viewer.PlotAreaMouseX);
            viewer.updateDisplay();
        }

        //
        // Draw the track line with legend
        //
        private void trackLineLegend(XYChart c, int mouseX)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = c.initDynamicLayer();

            // The plot area object
            PlotArea plotArea = c.getPlotArea();

            // Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
            double xValue = c.getNearestXValue(mouseX);
            int xCoor = c.getXCoor(xValue);

            // Draw a vertical track line at the x-position
            d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(0x000000, 0x0101));

            // Container to hold the legend entries
            var legendEntries = new List<string>();

            // Iterate through all layers to build the legend array
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    // We are only interested in visible data sets with names
                    string dataName = dataSet.getDataName();
                    int color = dataSet.getDataColor();
                    if ((!string.IsNullOrEmpty(dataName)) && (color != Chart.Transparent))
                    {
                        // Build the legend entry, consist of the legend icon, name and data value.
                        double dataValue = dataSet.getValue(xIndex);
                        legendEntries.Add("<*block*>" + dataSet.getLegendIcon() + " " + dataName + ": " + ((
                            dataValue == Chart.NoValue) ? "N/A" : c.formatValue(dataValue, "{value|P4}")) +
                            "<*/*>");

                        // Draw a track dot for data points within the plot area
                        int yCoor = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());
                        if ((yCoor >= plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()))
                        {
                            d.circle(xCoor, yCoor, 4, 4, color, color);
                        }
                    }
                }
            }

            // Create the legend by joining the legend entries
            legendEntries.Reverse();
            string legendText = "<*block,maxWidth=" + plotArea.getWidth() + "*><*block*><*font=Arial Bold*>["
                 + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") + "]<*/*>        " + String.Join(
                 "        ", legendEntries) + "<*/*>";

            // Display the legend on the top of the plot area
            TTFText t = d.text(legendText, "Arial", 8);
            t.draw(plotArea.getLeftX() + 5, plotArea.getTopY() - 3, 0x000000, Chart.BottomLeft);
        }
    }
}

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-18-2022 15:29
hi peter

Can u provide me the same sample above for winforms

regards
Abhishek

  Re: xAxis and YAxis panning
Posted by Peter Kwan on Apr-19-2022 14:46
Attachments:
Hi abhishek B L,

Attached please find the Wndows Forms version of the code.

Regards
Peter Kwan
frmzoomscrolltrack_xyzoom.zip
frmzoomscrolltrack_xyzoom.zip

8.99 Kb

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-19-2022 19:34
hi peter

can i get a homebutton in sample, where if we click on the it should show min and max of yaxis from o to 1

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-19-2022 22:32
hi peter

initially yaxis min and max value will be 0 and 1 after if i zoom on yaxis using mousewheel max and min value get changes,we have one button called homebutton where if user click on that max and min value of yaxis should be set as 1 and 0,but i am not getting can u help me out plsss

  Re: xAxis and YAxis panning
Posted by Peter Kwan on Apr-20-2022 04:34
Hi abhishek B L,

When the user push the button, please execute the following code:

// The following line is necessary if you have not already set the full range
myChartViewer.setFullRange("y", 0, 1);

// The following lines displays the full range
myChartViewer.ViewPortLeft = 0;
myChartViewer.ViewPortWidth = 1;
myChartViewer.updateViewPort(true, true);

Regards
Peter Kwan

  Re: xAxis and YAxis panning
Posted by Peter Kwan on Apr-20-2022 04:36
Hi abhishek B L,

Sorry, for the y-axis, it should set the ViewPortTop and ViewPortHeight:

myChartViewer.setFullRange("y", 0, 1);

// The following lines displays the full range
myChartViewer.ViewPortTop = 0;
myChartViewer.ViewPortHeight = 1;
myChartViewer.updateViewPort(true, true);

Regards
Peter Kwan

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-21-2022 12:46
Hi peter

Can we enable pan without using mousewheel,

  Re: xAxis and YAxis panning
Posted by abhishek B L on Apr-21-2022 13:21
hi peter

After zommin and Zoomout i want to scroll the values which is not visible up and down using panning and without using that mouse wheel , i just want drag using mouse and have to see those values which is not visible in yaxis can u help me out with this please

best regards
Abhishek

  Re: xAxis and YAxis panning
Posted by Peter Kwan on Apr-22-2022 12:47
Hi abhishek B L,

In the code I sent to you, it has:

viewer.ZoomDirection = viewer.ScrollDirection = WinChartDirection.HorizontalVertical;

So if you can use mouse drag to pan the chart horizontally, then you can also use mouse drag to pan the chart vertically.

If you cannot pan the chart vertically, it is probably because it is already displaying the full range, so there is nothing to pan.

As according to your previous message, I assume the full range is 0 to 1:

myChartViewer.setFullRange("y", 0, 1);

So if the y-axis is displaying 0 to 1, there is nothing more to pan, as it is already the full y-axis range. If you think it is not the full y-axis range, please configure it to your full y-axis range, or let ChartDirector automatically determine the full y-axis range by removing this line of code.

You previous also mentioned that you want to do thie followings:

      if we click on the it should show min and max of yaxis from o to 1

I am not too sure what the above means. Does it mean you want the full y-axis range to be 0 to 1 and the y-axis displays the full range?

If you do not know what is the y-axis range but want to display part of the y-axis scale from 0 to 1, then how do you know if the y-axis contains 0 to 1? For example, if the full y-axis range can be 0 to 0.4, in which case it cannot display 0 to 1. If you are certain your y-axis range contains 0 to 1, you can use:

// Your y-axis range, or remove it and let ChartDirector automatically determine from
// the first chart from the syncLinearAxisWithViewPort line.
myChartViewer.setFullRange("y", minValue, maxValue);

// When the home button is pressed, use:
myChartViewer.ViewPortTop = 1 - myChartViewer.getViewPortAtValue("y", 1);
myChartViewer.ViewPortHeight = myChartViewer.getViewPortAtValue("y", 1) - myChartViewer.getViewPortAtValue("y", 0);
myChartViewer.updateViewPort(true, true);

Regards
Peter Kwan