How to create zoom slider
Posted by Admin - on 21 March 2014 11:20 AM
We often get asked how to add a zoom slider to an axis. In this tutorial we will create a custom chart modifier to provide zoom slider functionality to a chart.

ScaleFactorModifier

Create a new class called ScaleFactorModifier using the following code.
using System;
using System.Windows;
using Abt.Controls.SciChart;
using Abt.Controls.SciChart.ChartModifiers;
using Abt.Controls.SciChart.Visuals.Axes;
 
namespace SciChartTutorials.Example
{
    /// <summary>
    /// Provides ability to bind zoom scale factor of a chart to a slider.
    /// </summary>
    public class ScaleFactorModifier : ChartModifierBase 
    {
        /// <summary>
        /// Prevents recursive calls of <see cref="SetZoomScaleFactor"/>.
        /// </summary>
        private bool _isUpdating;
 
        /// <summary>
        /// Defines the ZoomScaleFactor dependency property.
        /// </summary>
        public static readonly DependencyProperty ZoomScaleFactorProperty =
            DependencyProperty.Register("ZoomScaleFactor", typeof(double), typeof(ScaleFactorModifier), new PropertyMetadata(default(double), OnZoomScaleFactorChanged));
 
        /// <summary>
        /// Gets or sets zoom depth of the chart. It is calculated as Log10 of ratio between VisibleRange length and MaximumRange length
        /// (so, value of 0 means 100% zoom, value of -1 means 10% zoom etc.).
        /// </summary>
        public double ZoomScaleFactor
        {
            get { return (double)GetValue(ZoomScaleFactorProperty); }
            set { SetValue(ZoomScaleFactorProperty, value); }
        }
 
        /// <summary>
        /// Axis on which the zoom scale factor should be applied.
        /// </summary>
        public IAxis Axis { get { return ParentSurface.XAxis; } }
 
        private static void OnZoomScaleFactorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var @this = (ScaleFactorModifier)d;
            if (@this._isUpdating)
                return;
            @this.SetZoomScaleFactor(Math.Pow(10, (double)e.NewValue));
        }
 
        public override void OnAttached()
        {
            base.OnAttached();
            Axis.VisibleRangeChanged += OnVisibleRangeChanged;
            // First call to initialize the ZoomScaleFactor property.
            OnVisibleRangeChanged(this, null);
        }
 
        public override void OnDetached()
        {
            base.OnDetached();
            Axis.VisibleRangeChanged -= OnVisibleRangeChanged;
        }
 
        private void OnVisibleRangeChanged(object sender, VisibleRangeChangedEventArgs e)
        {
            _isUpdating = true;
            ZoomScaleFactor = Math.Log10(GetZoomScaleFactor());
            _isUpdating = false;
        }
 
        /// <summary>
        /// Gets linear zoom scale factor (i. e. without logarithm).
        /// </summary>
        /// <returns>The linear zoom scale factor.</returns>
        private double GetZoomScaleFactor()
        {
            return Axis.VisibleRange.AsDoubleRange().Diff / Axis.GetMaximumRange().AsDoubleRange().Diff;
        }
 
        /// <summary>
        /// Sets linear zoom scale factor (i. e. without logarithm).
        /// </summary>
        /// <param name="value">The new value.</param>
        private void SetZoomScaleFactor(double value)
        {
            var oldValue = GetZoomScaleFactor();
            var diff = value / (2 * oldValue) - 0.5;
            Axis.ZoomBy(diff, diff);
        }
    }
}
Now, if you add this modifier to a chart, you’ll be able to bind some dependency property to its ZoomScaleFactor property (or vice versa). Let’s take a look at an example.
<UserControl
    x:Class="Abt.Controls.SciChart.Example.Examples.IWantTo.CreateSimpleChart.BandSeriesChartExampleView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
    xmlns:example="clr-namespace:SciChartTutorials.Example"
    Loaded="BandSeriesChartExampleView_OnLoaded"
    d:DesignHeight="300"
    d:DesignWidth="300"
    mc:Ignorable="d">
 
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
 
        <s:SciChartSurface Name="sciChart" s:ThemeManager.Theme="BlackSteel">
 
            <s:SciChartSurface.ChartModifier>
                <example:ScaleFactorModifier x:Name="scaleFactorModifier" />
            </s:SciChartSurface.ChartModifier>
 
            <s:SciChartSurface.RenderableSeries>
                <s:FastBandRenderableSeries
                    BandDownColor="#33279B27"
                    BandUpColor="#33FF1919"
                    Series1Color="#FF279B27"
                    SeriesColor="#FFFF1919" />
            </s:SciChartSurface.RenderableSeries>
 
            <s:SciChartSurface.XAxis>
                <s:NumericAxis x:Name="xAxis" />
            </s:SciChartSurface.XAxis>
 
            <s:SciChartSurface.YAxis>
                <s:NumericAxis x:Name="yAxis" DrawMajorBands="True">
                    <s:NumericAxis.GrowBy>
                        <s:DoubleRange Max="0.1" Min="0.1" />
                    </s:NumericAxis.GrowBy>
                </s:NumericAxis>
            </s:SciChartSurface.YAxis>
        </s:SciChartSurface>
 
        <Slider
            Grid.Row="1"
            Maximum="0.1"
            Minimum="-2"
            Value="{Binding Path=ZoomScaleFactor, ElementName=scaleFactorModifier, Mode=TwoWay}" />
    </Grid>
</UserControl>
Now, if you move slider, the chart will zoom in and out, keeping the center of the visible range in the same point; and when you zoom by other means (RubberBand, Pinch etc.), the slider will also change its value.

Warnings

Performance

Due to calculating GetMaximumRange() on each update, this modifier can drop the performance on large amounts of data.

Non-linear axis

You’ll need to change the code a bit if you want to use this modifier on logarithmic axis. Essentially, you need to convert ranges to real length when you calculate GetZoomScaleFactor().

Clip mode

You will probably want to apply clip mode after zooming, so that if your visible range stacks to one edge of the chart series, the slider zoom would expand the chart only in the opposite direction. For that reason, create method
        private void ApplyClipMode()
        {
            var max = Axis.GetMaximumRange();
            if (!max.IsValueWithinRange(Axis.VisibleRange.Min))
                Axis.VisibleRange.Min = max.Min;
            if (!max.IsValueWithinRange(Axis.VisibleRange.Max))
                Axis.VisibleRange.Max = max.Max;
        }
and call it in the end of OnZoomScaleFactorChanged method.
(2 vote(s))
Helpful
Not helpful

CONTACT US

Not sure where to start? Contact us, we are happy to help!


CONTACT US

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL. Email: Legal Company Number: 07430048, VAT Number: 101957725