Charts frame size animation


#1

I’m trying to change the size of the frame for chart and animate the transition using UIView animations. The problem I’m having is that the openGL layer immediately gets resized to the new frame causing the graph to be stretched. The frame then animates to the new position and the graph ends up looking correct. 

I’ve tried using a CADisplayLink and moving the frame step by step but this causes a massive performance hit so the animation isn’t smooth.

Any ideas on what else I could try to get the desired result?


#2

I am having the similar problem so any help is more than welcome. 

I have overwritten the sChartRenderStarted and sChartRenderFinished in the delegate and I can just confirm that as soon as the UIView animation starts, those methods get called with the final frame size of the view (in my case it is same width and half of the height).


#3

Hi Guys,

I managed to get my chart animating smoothly using the 2.3 charts framework. Can I ask what version you are both using?

Jan


#4

Hi Jan,

I’m using the 2.3 API. The code below causes the problem. You can see when the animation first starts all the points double in size then return to the correct size as the animation runs.

@interface ViewController () <SChartDatasource>

@property (nonatomic, strong) ShinobiChart *chart;
@property (nonatomic, strong) SChartSeries* series;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.chart = [[ShinobiChart alloc] initWithFrame:self.view.bounds];
    self.chart.autoresizingMask = ~UIViewAutoresizingNone;
    self.chart.licenseKey = KEY;
    self.series = [self createSeries];
    self.chart.xAxis = [SChartNumberAxis new];
    self.chart.yAxis = [SChartNumberAxis new];
    self.chart.datasource = self;
    
    
    [self.view addSubview:self.chart];
    [self performSelector:@selector(doAnimation) withObject:nil afterDelay:3];
}

- (void) doAnimation {
    [UIView animateWithDuration:2 animations:^{
        self.chart.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height/2);
    }];
}

- (SChartSeries*) createSeries {
    SChartLineSeries *series = [[SChartLineSeries alloc] init];
    series.style.lineColor = [UIColor purpleColor];
    series.style.showFill = NO;
    series.crosshairEnabled = YES;
    series.style.pointStyle.radius = @10;
    series.style.pointStyle.color = [UIColor redColor];
    series.style.pointStyle.showPoints = YES;
    
    return series;
}

#pragma mark dataSource

// Returns the number of series in the specified chart
-(int) numberOfSeriesInSChart:(ShinobiChart *)chart
{
    return 1;
}

// Returns the series at the specified index for a given chart
-(SChartSeries *)sChart:(ShinobiChart *)chart seriesAtIndex:(int)index
{
    return self.series;
}

-(int)sChart:(ShinobiChart *)chart numberOfDataPointsForSeriesAtIndex:(int)seriesIndex
{
    return 50;
}

- (id<SChartData>)sChart:(ShinobiChart *)chart dataPointAtIndex:(int)dataIndex forSeriesAtIndex:(int)seriesIndex
{
    SChartDataPoint *dataPoint = [[SChartDataPoint alloc] init];
    
    dataPoint.xValue = @(dataIndex);
    dataPoint.yValue = @(dataIndex);
    
    return dataPoint;
}

#5

Ah Skorulis, I have just realised I misread your first post. You say that the plot area renders to its final animation size, becomes blurry as it is stretched and then animates to the correct frame size, whereby the graph looks correct.

I misunderstood what you were saying, as in older versions of the charting library, the plot area wouldn’t animate at all & would jump instantly - this is what I thought you were describing.

Unfortunately there isn’t a way around this. To get the plot area (the glView) to animate without blurring first, you would need to set the frame of the chart and animate it yourself manually. As you say, the animation in this case won’t be smooth on some devices as you are asking your chart to do quite a lot of work.

Here are a few ideas for workarounds / compramises that might be of interest to you.

Entry/Exit Animations

  • You could hide the chart series with some type of animation by setting an entry/exit animation on the series & hiding them.
  • Once then are hidden, you could then animate your entire chart using UIView animation.
  • Then display your series again after the animation completes.

Using an image

  • You could capture an image contents of the plot area’s view.
  • Place this image over your plot area.
  • Animate your chart using UIView animation as well as animating the image that is placed over the chart.
  • Remove the image.

Activity Indicator

  • Enable the charts activity indicator before resizing the chart.
  • Remove it after resizing the chart.

I hope the above helps you find a suitable solution. Let me know how you get on.

Thanks,
Jan