Search Results for

    Show / Hide Table of Contents

    Animations API

    In SciChart you can use Animations API to animate RenderableSeries. The Animations API is based on our Transformation API, which allows to define different IRenderPassDataTransformation to your ISeriesRenderPassData during the render pass.

    We provide helper AnimationsHelper class, which provides set of methods to create animations for IRenderableSeries.

    Let's see a simple example of using sweep animation on our Line Series:

    • Java
    • Java with Builders API
    • Kotlin
    // declare FastLineRenderableSeries to animate
    final FastLineRenderableSeries rSeries = new FastLineRenderableSeries();
    
    // Animate Line Series with Sweep Transformation
    AnimationsHelper.createAnimator(
            rSeries,
            new SweepXyTransformation<>(XyRenderPassData.class),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f, 1f
    ).start();
    
    // declare FastLineRenderableSeries to animate
    final FastLineRenderableSeries rSeries = sciChartBuilder.newLineSeries().build();
    
    // Animate Line Series with Sweep Transformation
    sciChartBuilder.newAnimator(rSeries)
            .withSweepTransformation()
            .withInterpolator(new DecelerateInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    // declare FastLineRenderableSeries to animate
    val rSeries = FastLineRenderableSeries()
    
    // Animate Line Series with Sweep Transformation
    AnimationsHelper.createAnimator(
        rSeries,
        SweepXyTransformation(XyRenderPassData::class.java),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    

    Under the hood AnimationsHelper methods creates Android Animator to animate specified series. After creation of animator you can combine them using AnimatorSet to animate several series at the same time or to create more complex animations.

    There are several default implementations of Tranformation API which allow to animate different series:

    Animation Types

    There are several animation types provided out of the box in SciChart:

    • Fade-In
    • Scale
    • Sweep
    • Wave
    • Translate-X
    • Translate-Y
    • Java
    • Java with Builders API
    • Kotlin
    // declare FastLineRenderableSeries to animate
    final FastLineRenderableSeries rSeries = new FastLineRenderableSeries();
    
    // Animate Line Series with Sweep Transformation
    AnimationsHelper.createAnimator(
            rSeries,
            new SweepXyTransformation<>(XyRenderPassData.class),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f, 1f
    ).start();
    
    // declare FastLineRenderableSeries to animate
    final FastLineRenderableSeries rSeries = sciChartBuilder.newLineSeries().build();
    
    // Animate Line Series with Sweep Transformation
    sciChartBuilder.newAnimator(rSeries)
            .withSweepTransformation()
            .withInterpolator(new DecelerateInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    // declare FastLineRenderableSeries to animate
    val rSeries = FastLineRenderableSeries()
    
    // Animate Line Series with Sweep Transformation
    AnimationsHelper.createAnimator(
        rSeries,
        SweepXyTransformation(XyRenderPassData::class.java),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    

    Fade-In Animation

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createOpacityAnimator(
            rSeries,
            2000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f, 1f
    ).start();
    
    sciChartBuilder.newOpacityAnimator(rSeries)
            .withDuration(2000)
            .withStartDelay(350)
            .start();
    
    AnimationsHelper.createOpacityAnimator(
        rSeries,
        2000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    
    Note

    The Fade-In animation is implemented utilizing the opacity property under the hood.

    Note

    Examples which uses Fade-In animation can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example

    Scale Animation

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createAnimator(
            rSeries,
            new ScaleXyTransformation<>(XyRenderPassData.class, 0),
            3000,
            350,
            new ElasticOutInterpolator(),
            new FloatEvaluator(),
            0f, 1f
    ).start();
    
    sciChartBuilder.newAnimator(rSeries)
            .withScaleTransformation()
            .withInterpolator(new ElasticOutInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    AnimationsHelper.createAnimator(
        rSeries,
        ScaleXyTransformation(XyRenderPassData::class.java, 0.0),
        3000,
        350,
        ElasticOutInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    
    Note

    The Scale animation is implemented utilizing the Scale Transformation under the hood.

    Note

    Examples which uses Scale animation can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example
    • Xamarin Example

    Sweep Animation

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createAnimator(
            rSeries,
            new SweepXyTransformation(XyRenderPassData.class),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f, 1f
    ).start();
    
    sciChartBuilder.newAnimator(rSeries)
            .withSweepTransformation()
            .withInterpolator(new DecelerateInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    AnimationsHelper.createAnimator(
        rSeries,
        SweepXyTransformation(XyRenderPassData::class.java),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    
    Note

    The Sweep animation is implemented utilizing the Sweep Transformation under the hood and available only for continuous series (e.g. Line, Mountain, Band etc...), where it's possible to interpolate points to have smooth animation.

    Note

    Examples which uses Sweep animation can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example
    • Xamarin Example

    Wave Animation

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createAnimator(
            rSeries,
            new WaveXyTransformation(XyRenderPassData.class, 0, 0.5f),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    sciChartBuilder.newAnimator(rSeries)
            .withWaveTransformation(0.5f)
            .withInterpolator(new DecelerateInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    AnimationsHelper.createAnimator(
        rSeries,
        WaveXyTransformation(XyRenderPassData::class.java, 0.0, 0.5f),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    
    Note

    The Wave animation is implemented utilizing the Wave Transformation under the hood.

    Note

    Examples which uses Wave animation can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example

    Translate-X Animation

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createAnimator(
            rSeries,
            new TranslateXTransformation(XyRenderPassData.class, -500),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    sciChartBuilder.newAnimator(rSeries)
            .withTranslateXTransformation(-500f)
            .withInterpolator(new DecelerateInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    AnimationsHelper.createAnimator(
        rSeries,
        TranslateXTransformation(XyRenderPassData::class.java, -500f),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    
    Note

    The Translate-X animation is implemented utilizing the Translate Transformation under the hood.

    Translate-Y Animation

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createAnimator(
            rSeries,
            new TranslateXyTransformation<>(XyRenderPassData.class, -500),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    sciChartBuilder.newAnimator(rSeries)
            .withTranslateYTransformation(-500f)
            .withInterpolator(new DecelerateInterpolator())
            .withDuration(3000)
            .withStartDelay(350)
            .start();
    
    AnimationsHelper.createAnimator(
        rSeries,
        TranslateXyTransformation(XyRenderPassData::class.java, -500f),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    
    Note

    The Translate-Y animation is implemented utilizing the Translate Transformation under the hood.

    Transformation API

    The Animations API is based on Tranformation API which allows to define different tranformations for IRenderableSeries which we apply during animation. When we start Animator created by Builders API or using AnimationsHelper directly it animates Progress of tranformation from 0 ( begining of animation ) to 1 ( end of animation ).

    There are several transformations provided out of the box which allow to animate different types of series:

    • Scale
    • Sweep
    • Wave
    • Translate-X
    • Translate-Y
    • Composite

    Scale Transformation

    Scale transformation is represented by the ScaleTransformationBase<T> and its implementors:

    Transformation Type Applicable to:
    ScaleXyTransformation<T> XyRenderPassData and inheritors.
    ScaleXyyTransformation<T> XyyRenderPassData and inheritors.
    ScaleXyzTransformation<T> XyzRenderPassData and inheritors.
    ScaleHlTransformation<T> HlRenderPassData and inheritors.
    ScaleOhlcTransformation<T> OhlcRenderPassData and inheritors.
    ScaleStackedXyTransformation<T> StackedSeriesRenderPassData and inheritors.
    Note

    The Scale Animation is implemented based on this transformation.

    Sweep Transformation

    Sweep transformation is represented by the SweepXyTransformation<T> and SweepXyyTransformation<T> which allows to transform XyRenderPassData and XyyRenderPassData respectively.

    Note

    The Sweep Animation is implemented base on this transformation.

    Wave Transformation

    Wave transformation is represented by the WaveTransformationBase<T> and its implementors:

    Transformation Type Applicable to:
    WaveXyTransformation<T> XyRenderPassData and inheritors.
    WaveXyyTransformation<T> XyyRenderPassData and inheritors.
    WaveHlTransformation<T> HlRenderPassData and inheritors.
    WaveOhlcTransformation<T> OhlcRenderPassData and inheritors.
    WaveStackedXyTransformation<T> StackedSeriesRenderPassData and inheritors.
    Note

    The Wave Animation is implemented based on this transformation.

    Translate Transformation

    Wave transformation is represented by the TranslateXTransformation<T> as well as TranslateXyTransformationBase<T> and its implementors:

    Transformation Type Applicable to:
    TranslateXTransformation<T> XSeriesRenderPassData and inheritors.
    TranslateXyTransformation<T> XyRenderPassData and inheritors.
    TranslateXyyTransformation<T> XyyRenderPassData and inheritors.
    TranslateHlTransformation<T> HlRenderPassData and inheritors.
    TranslateOhlcTransformation<T> OhlcRenderPassData and inheritors.
    TranslateStackedXyTransformation<T> StackedSeriesRenderPassData and inheritors.
    Note

    Translate-X and Translate-Y animations are implemented based on this transformation.

    Composite Transformation

    You might want to combine effects of several transformations at the same time without rewriting those into complex transformation. The CompositeTransformation is in SciChart to do just that. It allows to aggregate effects into one transformation (e.g. wave and translate-x)

    Let's try to use Wave and Translate-X at the same time, to animate Candlestick Series based on the Candlestick Chart example which can be found in the SciChart Android Examples Suite as well as on GitHub:

    • Native Example
    • Xamarin Example
    • Java
    • Java with Builders API
    • Kotlin
    // declare Candlestick Series to animate
    final FastCandlestickRenderableSeries rSeries = new FastCandlestickRenderableSeries();
    
    // Create transformations and make a Composite one out of them
    final WaveOhlcTransformation wave = new WaveOhlcTransformation(OhlcRenderPassData.class, 0, 0.5f);
    final TranslateXTransformation translateX = new TranslateXTransformation(OhlcRenderPassData.class, -300);
    final CompositeTransformation composite = new CompositeTransformation(wave, translateX);
    
    // Animate Candlestick Series with Composite Transformation
    AnimationsHelper.createAnimator(
            rSeries,
            composite,
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    // declare Candlestick Series to animate
    final FastCandlestickRenderableSeries rSeries = sciChartBuilder.newCandlestickSeries().build();
    
    // Create transformations and make a Composite one out of them
    final WaveOhlcTransformation wave = new WaveOhlcTransformation(OhlcRenderPassData.class, 0, 0.5f);
    final TranslateXTransformation translateX = new TranslateXTransformation(OhlcRenderPassData.class, -300);
    final CompositeTransformation composite = new CompositeTransformation(wave, translateX);
    
    // Animate Candlestick Series with Composite Transformation
    AnimationsHelper.createAnimator(
            rSeries,
            composite,
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    // declare Candlestick Series to animate
    val rSeries = FastCandlestickRenderableSeries()
    
    // Create transformations and make a Composite one out of them
    val wave = WaveOhlcTransformation(OhlcRenderPassData::class.java, 0.0, 0.5f)
    val translateX = TranslateXTransformation(OhlcRenderPassData::class.java, -300f)
    val composite = CompositeTransformation(wave, translateX)
    
    // Animate Candlestick Series with Composite Transformation
    AnimationsHelper.createAnimator(
        rSeries,
        composite,
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    

    which results in the following:

    Custom Animation

    To create custom animation we need to create a class which implements IRenderPassDataTransformation protocol. Inside we need to add code which modifies the render pass data of the RenderableSeries which we need to animate. For example, we'll try to animate line series and create expand effect which moves points from some predefined origin point.

    First we need to create a transformation for our XyRenderPassData:

    • Java
    • Java with Builders API
    • Kotlin
    class CustomXyTransformation extends BaseRenderPassDataTransformation<XyRenderPassData> {
        private final FloatValues originalXCoordinates = new FloatValues();
        private final FloatValues originalYCoordinates = new FloatValues();
    
        private final double centerX;
        private final double centerY;
    
        private float zeroXCoord, zeroYCoord;
    
        public CustomXyTransformation(double centerX, double centerY) {
            super(XyRenderPassData.class);
    
            this.centerX = centerX;
            this.centerY = centerY;
        }
    
        @Override
        protected void saveOriginalData() {
            final int count = renderPassData.pointsCount();
    
            // clear buffers
            originalXCoordinates.clear();
            originalYCoordinates.clear();
    
            // save initial xCoords and yCoords
            originalXCoordinates.add(renderPassData.xCoords.getItemsArray(), 0, count);
            originalYCoordinates.add(renderPassData.yCoords.getItemsArray(), 0, count);
    
            zeroXCoord = renderPassData.getXCoordinateCalculator().getCoordinate(centerX);
            zeroYCoord = renderPassData.getYCoordinateCalculator().getCoordinate(centerY);
        }
    
        @Override
        protected void applyTransformation() {
            // transform current render pass data
            transformValues(renderPassData.xCoords, originalXCoordinates, zeroXCoord);
            transformValues(renderPassData.yCoords, originalYCoordinates, zeroYCoord);
        }
        private void transformValues(FloatValues valuesToTransform, FloatValues originalCoordinates, float zeroCoord) {
            final float transformationValue = 1 - getCurrentTransformationValue();
            // calculate new values to display based on original value
            final float[] itemsArray = valuesToTransform.getItemsArray();
            final float[] originalValues = originalCoordinates.getItemsArray();
            for (int i = 0, size = renderPassData.pointsCount(); i < size; i++) {
                final float originalValue = originalValues[i];
                itemsArray[i] = originalValue - (originalValue - zeroCoord) * transformationValue;
            }
        }
    
        @Override
        protected void discardTransformation() {
            // clear coordinate buffers
            renderPassData.xCoords.clear();
            renderPassData.yCoords.clear();
    
            // save initial xCoords and yCoords
            renderPassData.xCoords.add(originalXCoordinates.getItemsArray(), 0, originalXCoordinates.size());
            renderPassData.yCoords.add(originalYCoordinates.getItemsArray(), 0, originalYCoordinates.size());
        }
        @Override
        protected void onInternalRenderPassDataChanged() { }
    }
    
    class CustomXyTransformation extends BaseRenderPassDataTransformation<XyRenderPassData> {
        private final FloatValues originalXCoordinates = new FloatValues();
        private final FloatValues originalYCoordinates = new FloatValues();
    
        private final double centerX;
        private final double centerY;
    
        private float zeroXCoord, zeroYCoord;
    
        public CustomXyTransformation(double centerX, double centerY) {
            super(XyRenderPassData.class);
    
            this.centerX = centerX;
            this.centerY = centerY;
        }
    
        @Override
        protected void saveOriginalData() {
            final int count = renderPassData.pointsCount();
    
            // clear buffers
            originalXCoordinates.clear();
            originalYCoordinates.clear();
    
            // save initial xCoords and yCoords
            originalXCoordinates.add(renderPassData.xCoords.getItemsArray(), 0, count);
            originalYCoordinates.add(renderPassData.yCoords.getItemsArray(), 0, count);
    
            zeroXCoord = renderPassData.getXCoordinateCalculator().getCoordinate(centerX);
            zeroYCoord = renderPassData.getYCoordinateCalculator().getCoordinate(centerY);
        }
    
        @Override
        protected void applyTransformation() {
            // transform current render pass data
            transformValues(renderPassData.xCoords, originalXCoordinates, zeroXCoord);
            transformValues(renderPassData.yCoords, originalYCoordinates, zeroYCoord);
        }
        private void transformValues(FloatValues valuesToTransform, FloatValues originalCoordinates, float zeroCoord) {
            final float transformationValue = 1 - getCurrentTransformationValue();
            // calculate new values to display based on original value
            final float[] itemsArray = valuesToTransform.getItemsArray();
            final float[] originalValues = originalCoordinates.getItemsArray();
            for (int i = 0, size = renderPassData.pointsCount(); i < size; i++) {
                final float originalValue = originalValues[i];
                itemsArray[i] = originalValue - (originalValue - zeroCoord) * transformationValue;
            }
        }
    
        @Override
        protected void discardTransformation() {
            // clear coordinate buffers
            renderPassData.xCoords.clear();
            renderPassData.yCoords.clear();
            
            // save initial xCoords and yCoords
            renderPassData.xCoords.add(originalXCoordinates.getItemsArray(), 0, originalXCoordinates.size());
            renderPassData.yCoords.add(originalYCoordinates.getItemsArray(), 0, originalYCoordinates.size());
        }
        @Override
        protected void onInternalRenderPassDataChanged() { }
    }
    
    class CustomXyTransformation(private val centerX: Double, private val centerY: Double) : BaseRenderPassDataTransformation<XyRenderPassData>(XyRenderPassData::class.java) {
        private val originalXCoordinates = FloatValues()
        private val originalYCoordinates = FloatValues()
    
        private var zeroXCoord = 0f
        private var zeroYCoord = 0f
    
        override fun saveOriginalData() {
            val count = renderPassData.pointsCount()
    
            // clear buffers
            originalXCoordinates.clear()
            originalYCoordinates.clear()
    
            // save initial xCoords and yCoords
            originalXCoordinates.add(renderPassData.xCoords.itemsArray, 0, count)
            originalYCoordinates.add(renderPassData.yCoords.itemsArray, 0, count)
            zeroXCoord = renderPassData.xCoordinateCalculator.getCoordinate(centerX)
            zeroYCoord = renderPassData.yCoordinateCalculator.getCoordinate(centerY)
        }
    
        override fun applyTransformation() {
            // transform current render pass data
            transformValues(renderPassData.xCoords, originalXCoordinates, zeroXCoord)
            transformValues(renderPassData.yCoords, originalYCoordinates, zeroYCoord)
        }
    
        private fun transformValues(
            valuesToTransform: FloatValues,
            originalCoordinates: FloatValues,
            zeroCoord: Float
        ) {
            val transformationValue = 1 - currentTransformationValue
            // calculate new values to display based on original value
            val itemsArray = valuesToTransform.itemsArray
            val originalValues = originalCoordinates.itemsArray
    
            var i = 0
            val size = renderPassData.pointsCount()
            while (i < size) {
                val originalValue = originalValues[i]
                itemsArray[i] = originalValue - (originalValue - zeroCoord) * transformationValue
                i++
            }
        }
    
        override fun discardTransformation() {
            // clear coordinate buffers
            renderPassData.xCoords.clear()
            renderPassData.yCoords.clear()
    
            // save initial xCoords and yCoords
            renderPassData.xCoords.add(originalXCoordinates.itemsArray, 0, originalXCoordinates.size())
            renderPassData.yCoords.add(originalYCoordinates.itemsArray, 0, originalYCoordinates.size())
        }
    
        override fun onInternalRenderPassDataChanged() {}
    }
    

    Then we use this custom transformation to animate series using AnimationsHelper APIs:

    • Java
    • Java with Builders API
    • Kotlin
    AnimationsHelper.createAnimator(
            rSeries,
            new CustomXyTransformation(150, 300),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    AnimationsHelper.createAnimator(
            rSeries,
            new CustomXyTransformation(150, 300),
            3000,
            350,
            new DecelerateInterpolator(),
            new FloatEvaluator(),
            0f,
            1f
    ).start();
    
    AnimationsHelper.createAnimator(
        rSeries,
        CustomXyTransformation(150.0, 300.0),
        3000,
        350,
        DecelerateInterpolator(),
        FloatEvaluator(),
        0f, 1f
    ).start()
    

    The result is the following:

    Back to top © 2011-2025 SciChart. All rights reserved. | sitemap.xml