SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, iOS Chart, Android Chart and JavaScript Chart Components
Please note! These examples are new to SciChart iOS v4 release! SciChart’s OpenGL ES and Metal iOS and Metal macOS Chart library ships with hundred of Objective-C and Swift iOS&macOS Chart Examples which you can browse, play with and view the source-code. All of this is possible with the new and improved SciChart iOS Examples Suite and demo application for Mac, which ships as part of the SciChart SDK.
Generates an iOS Shifted Axes in code. SciChart supports axis in the centre of the chart. It requires changes to the layout process in ISCILayoutManager to specify the exact axis position inside a chart area. See Documentation on how to use this type here: The iOS and macOS Shifted Axis Documentation.
The Swift and Objective-C source code for the iOS and macOS Digital Line Chart example is included below (Scroll down!).
Did you know that we have the source code for all our example available for free on Github?
Clone the SciChart.iOS.Examples from Github.
Also the SciChart iOS and Scichart macOS Trials contain the full source for the examples (link below).
//******************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2019. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// ShiftedAxesView.m is part of the SCICHART® Examples. Permission is hereby granted
// to modify, create derivative works, distribute and publish any part of this source
// code whether for commercial, private or personal use.
//
// The SCICHART® examples are distributed in the hope that they will be useful, but
// without any warranty. It is provided "AS IS" without warranty of any kind, either
// expressed or implied.
//******************************************************************************
#import "ShiftedAxesView.h"
#import "SCDDataManager.h"
#pragma mark - Inner Top/Left Layout Strategies
@interface CenteredTopAlignmentInnerAxisLayoutStrategy : SCITopAlignmentInnerAxisLayoutStrategy
- (instancetype)initWithYAxis:(id<ISCIAxis>)yAxis;
@end
@implementation CenteredTopAlignmentInnerAxisLayoutStrategy {
id<ISCIAxis> _yAxis;
}
- (instancetype)initWithYAxis:(id<ISCIAxis>)yAxis {
self = [super init];
if (self) {
_yAxis = yAxis;
}
return self;
}
- (void)layoutWithLeft:(CGFloat)left top:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom {
// find the coordinate of 0 on the Y Axis in pixels
// place the stack of the top-aligned X Axes at this coordinate
CGFloat topCoord = [_yAxis.currentCoordinateCalculator getCoordinateFrom:0];
[SCIHorizontalAxisLayoutStrategy layoutAxesFromTopToBottom:self.axes withLeft:left top:topCoord right:right];
}
@end
@interface CenteredLeftAlignmentInnerAxisLayoutStrategy : SCILeftAlignmentInnerAxisLayoutStrategy
- (instancetype)initWithXAxis:(id<ISCIAxis>)xAxis;
@end
@implementation CenteredLeftAlignmentInnerAxisLayoutStrategy {
id<ISCIAxis> _xAxis;
}
- (instancetype)initWithXAxis:(id<ISCIAxis>)xAxis {
self = [super init];
if (self) {
_xAxis = xAxis;
}
return self;
}
- (void)layoutWithLeft:(CGFloat)left top:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom {
// find the coordinate of 0 on the X Axis in pixels
// place the stack of the left-aligned Y Axes at this coordinate
CGFloat leftCoord = [_xAxis.currentCoordinateCalculator getCoordinateFrom:0];
[SCIVerticalAxisLayoutStrategy layoutAxesFromLeftToRight:self.axes withLeft:leftCoord top:top bottom:bottom];
}
@end
#pragma mark - Layout Manager
@interface CenterLayoutManager : NSObject<ISCILayoutManager>
- (instancetype)initWithXAxis:(id<ISCIAxis>)xAxis andYAxis:(id<ISCIAxis>)yAxis;
@end
@implementation CenterLayoutManager {
SCIDefaultLayoutManager *_layoutManager;
BOOL _isFirstLayout;
}
- (instancetype)initWithXAxis:(id<ISCIAxis>)xAxis andYAxis:(id<ISCIAxis>)yAxis {
self = [super init];
if (self) {
// need to override default inner layout strategies for bottom and right aligned axes
// because xAxis has right axis alignment and yAxis has bottom axis alignment
_layoutManager = [SCIDefaultLayoutManager new];
_layoutManager.leftInnerAxisLayoutStrategy = [[CenteredLeftAlignmentInnerAxisLayoutStrategy alloc] initWithXAxis:xAxis];
_layoutManager.topInnerAxisLayoutStrategy = [[CenteredTopAlignmentInnerAxisLayoutStrategy alloc] initWithYAxis:yAxis];
}
return self;
}
- (void)attachAxis:(id<ISCIAxis>)axis isXAxis:(BOOL)isXAxis {
[_layoutManager attachAxis:axis isXAxis:isXAxis];
}
- (void)detachAxis:(id<ISCIAxis>)axis {
[_layoutManager detachAxis:axis];
}
- (void)onAxisPlacementChanged:(id<ISCIAxis>)axis oldAxisAlignment:(SCIAxisAlignment)oldAxisAlignment oldIsCenterAxis:(BOOL)oldIsCenterAxis newAxisAlignment:(SCIAxisAlignment)newAxisAlignment newIsCenterAxis:(BOOL)newIsCenterAxis {
[_layoutManager onAxisPlacementChanged:axis oldAxisAlignment:oldAxisAlignment oldIsCenterAxis:oldIsCenterAxis newAxisAlignment:newAxisAlignment newIsCenterAxis:newIsCenterAxis];
}
- (void)attachTo:(id<ISCIServiceContainer>)services {
[_layoutManager attachTo:services];
// need to perform 2 layout passes during first layout of chart
_isFirstLayout = YES;
}
- (void)detach {
[_layoutManager detach];
}
- (BOOL)isAttached {
return _layoutManager.isAttached;
}
- (CGSize)onLayoutChartWithAvailableSize:(CGSize)size {
// need to perform additional layout pass if it is a first layout pass
// because we don't know correct size of axes during first layout pass
if (_isFirstLayout) {
[_layoutManager onLayoutChartWithAvailableSize:size];
_isFirstLayout = NO;
}
return [_layoutManager onLayoutChartWithAvailableSize:size];
}
@end
@implementation ShiftedAxesView
- (Class)associatedType { return SCIChartSurface.class; }
- (BOOL)showDefaultModifiersInToolbar { return NO; }
- (void)initExample {
id<ISCIAxis> xAxis = [self newAxisWithAlignment:SCIAxisAlignment_Top];
id<ISCIAxis> yAxis = [self newAxisWithAlignment:SCIAxisAlignment_Left];
SCDDoubleSeries *butterflyCurve = [SCDDataManager getButterflyCurve:20000];
SCIXyDataSeries *dataSeries = [[SCIXyDataSeries alloc] initWithXType:SCIDataType_Double yType:SCIDataType_Double];
dataSeries.acceptsUnsortedData = YES;
[dataSeries appendValuesX:butterflyCurve.xValues y:butterflyCurve.yValues];
SCIFastLineRenderableSeries *rSeries = [SCIFastLineRenderableSeries new];
rSeries.dataSeries = dataSeries;
[SCIUpdateSuspender usingWithSuspendable:self.surface withBlock:^{
self.surface.layoutManager = [[CenterLayoutManager alloc] initWithXAxis:xAxis andYAxis:yAxis];
[self.surface.xAxes add:xAxis];
[self.surface.yAxes add:yAxis];
[self.surface.renderableSeries add:rSeries];
[self.surface.chartModifiers add:[SCDExampleBaseViewController createDefaultModifiers]];
[SCIAnimations sweepSeries:rSeries duration:20 andEasingFunction:nil];
}];
}
- (id<ISCIAxis>)newAxisWithAlignment:(SCIAxisAlignment)axisAlignment {
id<ISCIAxis> axis = [SCINumericAxis new];
axis.axisAlignment = axisAlignment;
axis.majorTickLineStyle = [[SCISolidPenStyle alloc] initWithColorCode:0xFFFFFFFF thickness:2];
axis.textFormatting = @"0.00";
axis.drawMinorTicks = NO;
axis.isCenterAxis = YES;
axis.growBy = [[SCIDoubleRange alloc] initWithMin:0.1 max:0.1];
return axis;
}
@end
//******************************************************************************
// SCICHART® Copyright SciChart Ltd. 2011-2019. All rights reserved.
//
// Web: http://www.scichart.com
// Support: support@scichart.com
// Sales: sales@scichart.com
//
// ShiftedAxesView.swift is part of the SCICHART® Examples. Permission is hereby granted
// to modify, create derivative works, distribute and publish any part of this source
// code whether for commercial, private or personal use.
//
// The SCICHART® examples are distributed in the hope that they will be useful, but
// without any warranty. It is provided "AS IS" without warranty of any kind, either
// expressed or implied.
//******************************************************************************
// MARK: - Inner Top/Left Layout Strategies
class CenteredTopAlignmentInnerAxisLayoutStrategy: SCITopAlignmentInnerAxisLayoutStrategy {
let yAxis: ISCIAxis;
init(yAxis: ISCIAxis) {
self.yAxis = yAxis
}
override func layout(withLeft left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat) {
// find the coordinate of 0 on the Y Axis in pixels
// place the stack of the top-aligned X Axes at this coordinate
let topCoord = CGFloat(yAxis.currentCoordinateCalculator.getCoordinate(0))
SCIHorizontalAxisLayoutStrategy.layoutAxesFromTop(toBottom: self.axes as! [ISCIAxis], withLeft: left, top: topCoord, right: right)
}
}
class CenteredLeftAlignmentInnerAxisLayoutStrategy: SCILeftAlignmentInnerAxisLayoutStrategy {
let xAxis: ISCIAxis;
init(xAxis: ISCIAxis) {
self.xAxis = xAxis
}
override func layout(withLeft left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat) {
// find the coordinate of 0 on the X Axis in pixels
// place the stack of the left-aligned Y Axes at this coordinate
let leftCoord = CGFloat(xAxis.currentCoordinateCalculator.getCoordinate(0))
SCIVerticalAxisLayoutStrategy.layoutAxesFromLeft(toRight: self.axes as! [ISCIAxis], withLeft: leftCoord, top: top, bottom: bottom)
}
}
// MARK: - Layout Manager
class CenterLayoutManager: NSObject, ISCILayoutManager {
let layoutManager = SCIDefaultLayoutManager()
var isFirstLayout = false
init(xAxis: ISCIAxis, yAxis: ISCIAxis) {
// need to override default inner layout strategies for bottom and right aligned axes
// because xAxis has right axis alignment and yAxis has bottom axis alignment
layoutManager.leftInnerAxisLayoutStrategy = CenteredLeftAlignmentInnerAxisLayoutStrategy(xAxis: xAxis)
layoutManager.topInnerAxisLayoutStrategy = CenteredTopAlignmentInnerAxisLayoutStrategy(yAxis: yAxis)
}
func attach(_ axis: ISCIAxis, isXAxis: Bool) {
layoutManager.attach(axis, isXAxis: isXAxis)
}
func detach(_ axis: ISCIAxis) {
layoutManager.detach(axis)
}
func onAxisPlacementChanged(_ axis: ISCIAxis, oldAxisAlignment: SCIAxisAlignment, oldIsCenterAxis: Bool, newAxisAlignment: SCIAxisAlignment, newIsCenterAxis: Bool) {
layoutManager.onAxisPlacementChanged(axis, oldAxisAlignment: oldAxisAlignment, oldIsCenterAxis: oldIsCenterAxis, newAxisAlignment: newAxisAlignment, newIsCenterAxis: newIsCenterAxis)
}
func attach(to services: ISCIServiceContainer) {
layoutManager.attach(to: services)
// need to perform 2 layout passes during first layout of chart
isFirstLayout = true
}
func detach() {
layoutManager.detach()
}
var isAttached: Bool {
get { return layoutManager.isAttached }
}
func onLayoutChart(withAvailableSize size: CGSize) -> CGSize {
// need to perform additional layout pass if it is a first layout pass
// because we don't know correct size of axes during first layout pass
if isFirstLayout {
layoutManager.onLayoutChart(withAvailableSize: size)
isFirstLayout = false
}
return layoutManager.onLayoutChart(withAvailableSize: size)
}
}
class ShiftedAxesView: SCDSingleChartViewController<SCIChartSurface> {
override var associatedType: AnyClass { return SCIChartSurface.self }
override var showDefaultModifiersInToolbar: Bool { return false }
override func initExample() {
let xAxis = newAxis(axisAlignment: .top)
let yAxis = newAxis(axisAlignment: .left)
let butterflyCurve = SCDDataManager.getButterflyCurve(20000)
let dataSeries = SCIXyDataSeries(xType: .double, yType: .double)
dataSeries.acceptsUnsortedData = true
dataSeries.append(x: butterflyCurve.xValues, y: butterflyCurve.yValues)
let rSeries = SCIFastLineRenderableSeries()
rSeries.dataSeries = dataSeries
SCIUpdateSuspender.usingWith(surface) {
self.surface.layoutManager = CenterLayoutManager(xAxis: xAxis, yAxis: yAxis)
self.surface.xAxes.add(xAxis)
self.surface.yAxes.add(yAxis)
self.surface.renderableSeries.add(rSeries)
self.surface.chartModifiers.add(SCDExampleBaseViewController.createDefaultModifiers())
SCIAnimations.sweep(rSeries, duration: 20, easingFunction: nil)
}
}
func newAxis(axisAlignment: SCIAxisAlignment) -> ISCIAxis {
let axis = SCINumericAxis()
axis.axisAlignment = axisAlignment
axis.majorTickLineStyle = SCISolidPenStyle(color: 0xFFFFFFFF, thickness: 2)
axis.textFormatting = "0.00"
axis.drawMinorTicks = false
axis.isCenterAxis = true
axis.growBy = SCIDoubleRange(min: 0.1, max: 0.1)
return axis
}
}