SciChart WPF 2D Charts > Axis APIs > Axis APIs - Programmatically Zoom, Scroll and Axis
Axis APIs - Programmatically Zoom, Scroll and Axis

Programmatically Scrolling an Axis

SciChart provides a clean and simple API to interact with a single Axis programmatically, e.g. to Zoom, Scroll or Pan an axis. This can come in useful when creating custom ChartModifierBase derived classes e.g. custom zooming or panning of the chart.

IAxis Interactivity Methods

The following methods can be found on IAxis and AxisBase, a shared base-class for Axis types in SciChart.

IAxis Interactivity Methods
Copy Code
/// <summary>
/// Scrolls current <see cref="IAxisParams.VisibleRange"/> by the specified number of pixels
/// </summary>
/// <param name="pixelsToScroll">Scroll N pixels from the current visible range</param>
/// <param name="clipMode">Defines how scrolling behaves when you reach the edge of the Axis extents.
/// e.g. ClipMode.ClipAtExtents prevents panning outside of the Axis, ClipMode.None allows panning outside</param>
void Scroll(double pixelsToScroll, ClipMode clipMode);

/// <summary>
/// Scrolls current <see cref="IAxisParams.VisibleRange"/> by the specified number of pixels with the specified animation duration
/// </summary>
/// <param name="pixelsToScroll">Scroll N pixels from the current visible range</param>
/// <param name="clipMode">Defines how scrolling behaves when you reach the edge of the Axis extents.
/// e.g. ClipMode.ClipAtExtents prevents panning outside of the Axis, ClipMode.None allows panning outside</param>
/// <param name="duration">The duration of animation when zooming to extents</param>
void Scroll(double pixelsToScroll, ClipMode clipMode, TimeSpan duration);

/// <summary>
/// Translates current <see cref="IAxisParams.VisibleRange"/> by the specified number of datapoints
/// </summary>
/// <param name="pointAmount">Amount of data points that the start visible range is scrolled by</param>
/// <remarks>For XAxis only, is suitable for <see cref="CategoryDateTimeAxis"/>, <see cref="DateTimeAxis"/> and <see cref="NumericAxis"/>
/// where data is regularly spaced</remarks>
void ScrollBy(int pointAmount);

/// <summary>
/// Translates current <see cref="IAxisParams.VisibleRange"/> by the specified number of datapoints with the specified animation duration
/// </summary>
/// <param name="pointAmount">Amount of points that the start visible range is scrolled by</param>
/// <remarks>For XAxis only, is suitable for <see cref="CategoryDateTimeAxis"/>, <see cref="DateTimeAxis"/> and <see cref="NumericAxis"/>
/// where data is regularly spaced</remarks>
/// <param name="duration">The duration of animation when zooming to extents</param>
void ScrollBy(int pointAmount, TimeSpan duration);

/// <summary>
/// Performs zoom on current <see cref="IAxis"/>, using <paramref name="fromCoord"/> as a coordinate of new range start and
/// <paramref name="toCoord"/> as a coordinate of new range end
/// </summary>
/// <param name="fromCoord">The coordinate of new range start in pixels</param>
/// <param name="toCoord">The coordinate of new range end in pixels</param>
void Zoom(double fromCoord, double toCoord);

/// <summary>
/// Performs zoom on current <see cref="IAxis"/>, using <paramref name="fromCoord"/> as a coordinate of new range start and
/// <paramref name="toCoord"/> as a coordinate of new range end
/// </summary>
/// <param name="fromCoord">The coordinate of new range start in pixels</param>
/// <param name="toCoord">The coordinate of new range end in pixels</param>
/// <param name="duration">The duration of animation when zooming to extents</param>
void Zoom(double fromCoord, double toCoord, TimeSpan duration);

/// <summary>
/// Performs zoom on current <see cref="IAxis"/>, using <paramref name="minFraction"/> as a multiplier of range start and
/// <paramref name="maxFraction"/> as a multiplier of range end
/// </summary>
/// <param name="minFraction">The multiplier of range start</param>
/// <param name="maxFraction">The multiplier of range end</param>
void ZoomBy(double minFraction, double maxFraction);

/// <summary>
/// Performs zoom on current <see cref="IAxis"/>, using <paramref name="minFraction"/> as a multiplier of range start and
/// <paramref name="maxFraction"/> as a multiplier of range end
/// </summary>
/// <param name="minFraction">The multiplier of range start</param>
/// <param name="maxFraction">The multiplier of range end</param>
/// <param name="duration">The duration of animation when zooming to extents</param>
void ZoomBy(double minFraction, double maxFraction, TimeSpan duration);

Using Axis.Scroll()

A simple example below shows how you can use Axis.Scroll() in combination with the ChartModifierBase API to create a simple custom ZoomPanModifier. Include this on your chart like any other modifier, by setting SciChartSurface.ChartModifier = new SimpleZoomPanModifier();

Using Axis.Scroll()
Copy Code
/// <summary>
/// A single X-Y axis implementation of a ZoomPanModifier, used to demonstrate the ChartModifierBase and Axis Interactivity APIs in SciChart
/// </summary>
public class SimpleZoomPanModifier : ChartModifierBase
{
    private Point? _lastPoint;

    public override void OnModifierMouseDown(ModifierMouseArgs e)
    {
        base.OnModifierMouseDown(e);

        e.Handled = true;
        _lastPoint = e.MousePoint;
    }

    public override void OnModifierMouseMove(ModifierMouseArgs e)
    {
        base.OnModifierMouseMove(e);
        if (_lastPoint == null) return;

        var currentPoint = e.MousePoint;
        var xDelta = currentPoint.X - _lastPoint.Value.X;
        var yDelta = _lastPoint.Value.Y - currentPoint.Y;

        using (ParentSurface.SuspendUpdates())
        {
            // Scroll the XAxis by the number of pixels since the last update
            XAxis.Scroll(XAxis.IsHorizontalAxis ? xDelta : -yDelta, ClipMode.None);

            // Scroll the YAxis by the number of pixels since the last update
            YAxis.Scroll(YAxis.IsHorizontalAxis ? -xDelta : yDelta, ClipMode.None);

            // Note.. can be extended for multiple YAxis XAxis, just iterate over all axes on the parent surface
        }

        _lastPoint = currentPoint;
    }

    public override void OnModifierMouseUp(ModifierMouseArgs e)
    {
        base.OnModifierMouseUp(e);
        _lastPoint = null;
    }
}

Using Axis.Zoom()

A simple example below shows how you can use Axis.Zoom() in combination with the ChartModifierBase API to create a simple custom modifier which handles KeyDown and zooms in and out on CTRL+ or CTRL- Key Presses.

Include this on your chart like any other modifier, by setting SciChartSurface.ChartModifier = new SimpleZoomInOutModifier();

Using Axis.Zoom()
Copy Code
/// <summary>
/// A single X-Y axis implementation of a Zooming In / Out on KeyDown (CTRL+, CTRL-), used to demonstrate the ChartModifierBase and Axis Interactivity APIs in SciChart
/// </summary>
public class SimpleZoomInOutModifier : ChartModifierBase
{
    public static readonly DependencyProperty ZoomFractionProperty = DependencyProperty.Register("ZoomFraction", typeof (double), typeof (SimpleZoomInOutModifier), new PropertyMetadata(0.1));

    public double ZoomFraction
    {
        get { return (double) GetValue(ZoomFractionProperty); }
        set { SetValue(ZoomFractionProperty, value); }
    }

    void SciChart_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        double factor = 0;
             
        if (e.Key == Key.Add && (Keyboard.Modifiers & ModifierKeys.Control) > 0)
        {
            // On CTRL+, Zoom In
            factor = -ZoomFraction;
        }
        if (e.Key == Key.Subtract && (Keyboard.Modifiers & ModifierKeys.Control) > 0)
        {
            // On CTRL-, Zoom Out
            factor = ZoomFraction;
        }

        using (ParentSurface.SuspendUpdates())
        {
            // Zoom the XAxis by the required factor
            XAxis.ZoomBy(factor, factor, TimeSpan.FromMilliseconds(500));

            // Zoom the YAxis by the required factor
            YAxis.ZoomBy(factor, factor, TimeSpan.FromMilliseconds(500));

            // Note.. can be extended for multiple YAxis XAxis, just iterate over all axes on the parent surface
        }
    }

    public override void OnAttached()
    {
        base.OnAttached();
        var scichart = ((SciChartSurface)ParentSurface);

        var mainWindow = FindLogicalParent<Window>(scichart);

        mainWindow.PreviewKeyDown -= SciChart_PreviewKeyDown;
        mainWindow.PreviewKeyDown += SciChart_PreviewKeyDown;
    }

    private T FindLogicalParent<T>(SciChartSurface scichart) where T:class
    {
        var parent = (FrameworkElement)scichart.Parent;
        while (parent != null)
        {
            var candidate = parent as T;
            if (candidate != null) return candidate;

            parent = (FrameworkElement)parent.Parent;
        }

        return null;
    }
} 

See Also