Animations API - Animate Updated Point
SciChart library has several built-in animations which you can use to animate your Renderable Series.
Note
Please refer to the Animations API article for more details.
Also, you can create a custom animation and have complete control over data appearing on the screen. This tutorial shows how to animate Y-Value changes of StackedColumnRenderableSeries in real-time.
To achieve that we'd need to perform 2 steps:
- Create a new transformation - a class that implements a IRenderPassDataTransformation protocol.
- Animate your series using previously created transformation
Note
A complete project of the Animated Stacked Column Series example you can find in the SciChart Android Examples Suite as well as on GitHub:
Create transformation
Creating transformation is fairly simple. We have to create a class that implements an IRenderPassDataTransformation protocol and pass an ISeriesRenderPassData type suitable for your Renderable Series. In our case we will subclass an abstract class BaseRenderPassDataTransformation<TRenderPassData>, pass StackedColumnRenderPassData type and implement few required methods. The code would look like follows:
class UpdatedPointTransformation extends BaseRenderPassDataTransformation<StackedColumnRenderPassData> {
private final FloatValues previousYCoordinates = new FloatValues();
private final FloatValues previousPrevSeriesYCoordinates = new FloatValues();
private final FloatValues originalYCoordinates = new FloatValues();
private final FloatValues originalPrevSeriesYCoordinates = new FloatValues();
protected UpdatedPointTransformation() {
super(StackedColumnRenderPassData.class);
}
@Override
protected void saveOriginalData() {
if (!renderPassData.isValid()) return;
TransformationHelpers.copyData(renderPassData.yCoords, originalYCoordinates);
TransformationHelpers.copyData(renderPassData.prevSeriesYCoords, originalPrevSeriesYCoordinates);
}
@Override
protected void applyTransformation() {
if (!renderPassData.isValid()) return;
int count = renderPassData.pointsCount();
float currentTransformationValue = getCurrentTransformationValue();
if (previousPrevSeriesYCoordinates.size() != count ||
previousYCoordinates.size() != count ||
originalYCoordinates.size() != count ||
originalPrevSeriesYCoordinates.size() != count) return;
for (int i = 0; i < count; i++) {
float startYCoord = previousYCoordinates.get(i);
float originalYCoordinate = originalYCoordinates.get(i);
float additionalY = startYCoord + (originalYCoordinate - startYCoord) * currentTransformationValue;
float startPrevSeriesYCoords = previousPrevSeriesYCoordinates.get(i);
float originalPrevSeriesYCoordinate = originalPrevSeriesYCoordinates.get(i);
float additionalPrevSeriesY = startPrevSeriesYCoords + (originalPrevSeriesYCoordinate - startPrevSeriesYCoords) * currentTransformationValue;
renderPassData.yCoords.set(i, additionalY);
renderPassData.prevSeriesYCoords.set(i, additionalPrevSeriesY);
}
}
@Override
protected void discardTransformation() {
TransformationHelpers.copyData(originalYCoordinates, renderPassData.yCoords);
TransformationHelpers.copyData(originalPrevSeriesYCoordinates, renderPassData.prevSeriesYCoords);
}
@Override
protected void onInternalRenderPassDataChanged() {
applyTransformation();
}
@Override
public void onAnimationEnd() {
super.onAnimationEnd();
TransformationHelpers.copyData(originalYCoordinates, previousYCoordinates);
TransformationHelpers.copyData(originalPrevSeriesYCoordinates, previousPrevSeriesYCoordinates);
}
}
Animate series
With the transformation created above, all we need to do is just animate our series. It's easily achievable with AnimationsHelper APIs like below:
// Since we have two Renderable Series in our `VerticallyStackedColumnsCollection`, we need to create separate animators for each series. Please refer to a complete example for more details.
Animator animator1 = createAnimator(rSeries1);
Animator animator2 = createAnimator(rSeries2);
private Animator createAnimator(StackedColumnRenderableSeries rSeries) {
return AnimationsHelper.createAnimator(
rSeries,
new UpdatedPointTransformation(),
ANIMATION_DURATION,
0,
new DecelerateInterpolator(),
new FloatEvaluator(),
0f, 1f
);
}
// this method is called in real time based on timer.
private void refreshData() {
requireActivity().runOnUiThread(() -> {
//cancel animators in case they are in progress
animator1.cancel();
animator2.cancel();
UpdateSuspender.using(binding.surface, () -> {
for (int i = 0; i < X_VALUES_COUNT; i++) {
dataSeries1.updateYAt(i, getRandomYValue());
dataSeries2.updateYAt(i, getRandomYValue());
}
});
// start animation
animator1.start();
animator2.start();
});
}
Note
You may also take a look at the Animations API - Animate Appended Point article to find out how to animate an appended point.