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 the last appended point to a SCIFastLineRenderableSeries in real-time.
#import <SciChart/SCIBaseRenderPassDataTransformation+Protected.h>
@interface SCDAppendedPointTransformation : SCIBaseRenderPassDataTransformation
- (instancetype)init;
@end
@implementation SCDAppendedPointTransformation {
SCIFloatValues *_originalXCoordinates;
SCIFloatValues *_originalYCoordinates;
}
- (instancetype)init {
self = [super initWithRenderPassDataType:SCILineRenderPassData.class];
if (self) {
_originalXCoordinates = [SCIFloatValues new];
_originalYCoordinates = [SCIFloatValues new];
}
return self;
}
// this method is called before the animation starts
- (void)saveOriginalData {
if (!self.renderPassData.isValid) return;
// save initial xCoords and yCoords
[SCITransformationHelpers copyDataFromSource:self.renderPassData.xCoords toDest:_originalXCoordinates];
[SCITransformationHelpers copyDataFromSource:self.renderPassData.yCoords toDest:_originalYCoordinates];
}
// this method is called multiple times in a loop while the animation is in progress.
- (void)applyTransformation {
if (!self.renderPassData.isValid) return;
id xCalculator = self.renderPassData.xCoordinateCalculator;
id yCalculator = self.renderPassData.yCoordinateCalculator;
NSInteger count = self.renderPassData.pointsCount;
// calculate new values for a renderPassData based on original values and the current animator fraction
float firstXStart = [xCalculator getCoordinateFrom:0];
float xStart = count <= 1 ? firstXStart : [_originalXCoordinates getValueAt:count - 2];
float xFinish = [_originalXCoordinates getValueAt:count - 1];
float additionalX = xStart + (xFinish - xStart) * self.currentTransformationValue;
[self.renderPassData.xCoords set:additionalX at:count - 1];
float firstYStart = [yCalculator getCoordinateFrom:0];
float yStart = count <= 1 ? firstYStart : [_originalYCoordinates getValueAt:count - 2];
float yFinish = [_originalYCoordinates getValueAt:count - 1];
float additionalY = yStart + (yFinish - yStart) * self.currentTransformationValue;
[self.renderPassData.yCoords set:additionalY at:count - 1];
}
// this method is called on clean up after animation end
- (void)discardTransformation {
// reset renderPassData to initial xCoords and yCoords
[SCITransformationHelpers copyDataFromSource:_originalXCoordinates toDest:self.renderPassData.xCoords];
[SCITransformationHelpers copyDataFromSource:_originalYCoordinates toDest:self.renderPassData.yCoords];
}
- (void)onInternalRenderPassDataChanged {
[self applyTransformation];
}
@end
import SciChart.Protected.SCIBaseRenderPassDataTransformation
class AppendedPointTransformation: SCIBaseRenderPassDataTransformation {
private let originalXCoordinates = SCIFloatValues()
private let originalYCoordinates = SCIFloatValues()
init() {
super.init(renderPassDataType: SCILineRenderPassData.self)
}
// this method is called before the animation starts
override func saveOriginalData() {
guard let renderPassData = self.renderPassData, renderPassData.isValid else { return }
// save initial xCoords and yCoords
SCITransformationHelpers.copyData(fromSource: renderPassData.xCoords, toDest: originalXCoordinates)
SCITransformationHelpers.copyData(fromSource: renderPassData.yCoords, toDest: originalYCoordinates)
}
// this method is called multiple times in a loop while the animation is in progress.
override func applyTransformation() {
guard
let renderPassData = self.renderPassData,
renderPassData.isValid,
let xCalculator = renderPassData.xCoordinateCalculator,
let yCalculator = renderPassData.yCoordinateCalculator
else { return }
let count = renderPassData.pointsCount
// calculate new values for a renderPassData based on original values and the current animator fraction
let firstXStart = xCalculator.getCoordinate(0)
let xStart = count <= 1 ? firstXStart : originalXCoordinates.getValueAt(count - 2)
let xFinish = originalXCoordinates.getValueAt(count - 1)
let additionalX = xStart + (xFinish - xStart) * currentTransformationValue
renderPassData.xCoords.set(additionalX, at: count - 1)
let firstYStart = yCalculator.getCoordinate(0)
let yStart = count <= 1 ? firstYStart : originalYCoordinates.getValueAt(count - 2)
let yFinish = originalYCoordinates.getValueAt(count - 1)
let additionalY = yStart + (yFinish - yStart) * currentTransformationValue
renderPassData.yCoords.set(additionalY, at: count - 1)
}
// this method is called on clean up after animation end
override func discardTransformation() {
guard let renderPassData = self.renderPassData else { return }
// reset renderPassData to initial xCoords and yCoords
SCITransformationHelpers.copyData(fromSource: originalXCoordinates, toDest: renderPassData.xCoords)
SCITransformationHelpers.copyData(fromSource: originalYCoordinates, toDest: renderPassData.yCoords)
}
override func onInternalRenderPassDataChanged() {
applyTransformation()
}
}
Animate series
With the transformation created above, all we need to do is just animate our series.
It’s easily achievable with SCIAnimations APIs like below:
// Append new value to our dataSeries in real-time
double randomYValue = SCDRandomUtil.nextDouble() * self.maxYValue
[self->_dataSeries appendX:@(self->_currentXValue) y:@(randomYValue)];
// Animate renderable series with our custom transformation
[SCIAnimations animateSeries:_rSeries withTransformation:[SCDAppendedPointTransformation new] duration:animationDuration andEasingFunction:[SCICubicEase new]];
// Append new value to our dataSeries in real-time
let randomYValue = SCDRandomUtil.nextDouble() * self.maxYValue
self.dataSeries.append(x: self.currentXValue, y: randomYValue)
// Animate renderable series with our custom transformation
SCIAnimations.animate(rSeries, with: AppendedPointTransformation(), duration: animationDuration, andEasingFunction: SCICubicEase())
NOTE: You may also take a look at the Animations API - Animate Updated Point article to find out how to animate Series after updating existing data points.