Sorry if this issue duplicates any already opened or closed. I didn't find such issues.
Problem is with auto-scaling - it's unstable and representation of data has some problems. Here's a video of the problem.
https://drive.google.com/open?id=1Li2iWG6BXOR1XwIHM0gU0SV6cRxG0o3R
I will be grateful for any advice that could handle this problem with this pod.
Can you provide more details? A reproducable example, what have you tried to debug, etc. (Stack Overflow rules).
@liuxuan30 Might already have experience with this.
it's known issue I remember, but complicated
Thank you for so quick response and sorry for late mine. I cannot share the copy of the project and do not have enough time to create a separate one.
I see that the problem is caused by loop rerendering with different length of Y label axes on each step of rendering (Max was 800(3) and 1000(4) in each state). Different label length makes the chart recalculate the amount of displayed bars and each step is unstable. I fixed that with custom YAxisValueFormatter. For people who will be going after me - here is my code:
// YAxisValueFormatter.h
// Copyright © 2018 Anton Komir. All rights reserved.
//
#import <UIKit/UIKit.h>
@import Charts;
@interface YAxisValueFormatter : NSObject <IChartAxisValueFormatter>
- (id)initForChart:(BarLineChartViewBase *)chart;
@end
// YAxisValueFormatter.m
// Copyright © 2018 Anton Komir. All rights reserved.
//
#import "YAxisValueFormatter.h"
@implementation YAxisValueFormatter
{
NSArray *months;
__weak BarLineChartViewBase *_chart;
}
- (id)initForChart:(BarLineChartViewBase *)chart
{
self = [super init];
if (self)
{
self->_chart = chart;
}
return self;
}
- (NSString *)stringForValue:(double)value
axis:(ChartAxisBase *)axis
{
int maxLenght = 7;
NSString *result = [NSString stringWithFormat:@"%i", (int)value];
int valueLenght = [result length];
int difference = maxLenght - valueLenght;
for (int i = 0; i < difference; i++) {
result = [NSString stringWithFormat:@" %@", result];
}
return result;
}
@end
I know that not the best solution.
Also, small comment - that bug reproduced also in the Android version of the library.
yes, that's why I said it's kind of complex, as iOS portion just reimplement what Android does. And for autoScaleMinMaxEnabled feature, we don't have people really look into it yet.
@liuxuan30 Are you able to make a ticket describing what exactly the issue is and I will investigate it.
let's aim at current swift and later take a look at this. I will create a project for it
@AntonNix not sure if you have resolved this already, but I was notifying a similar y-axis glitch when doing a real-time chart with many points requiring auto-scaling.
In previous version of my app, I had my update function as following
func updateChart() {
data?.notifyDataChanged()
setVisibleXRange(minXRange: minXRange, maxXRange: maxXRange)
self.notifyDataSetChanged()
moveViewToX(Double(sets[0].entryCount) + xAxisOffset)
}
After updating to the latest charts, I removed self.notifyDataSetChanged as I read somewhere @liuxuan30 mentioned that was no need to do this as data.notifyDataSetChanged should be sufficient. Turns out its not.
@liuxuan30 @danielgindi Hi ,not only my project met the problem, but also ChartsDemo-iOS met the same problem!When I scale and move one candle stick to the edge,the chart was blinking !
I guess the chart redraw went wrong !
in chart demo ,I record a video below:
Chart demo video.zip
Hope any help or reply,Thanks~
Thank you for so quick response and sorry for late mine. I cannot share the copy of the project and do not have enough time to create a separate one.
I see that the problem is caused by loop rerendering with different length of Y label axes on each step of rendering (Max was 800(3) and 1000(4) in each state). Different label length makes the chart recalculate the amount of displayed bars and each step is unstable. I fixed that with custom YAxisValueFormatter. For people who will be going after me - here is my code:// YAxisValueFormatter.h // Copyright © 2018 Anton Komir. All rights reserved. // #import <UIKit/UIKit.h> @import Charts; @interface YAxisValueFormatter : NSObject <IChartAxisValueFormatter> - (id)initForChart:(BarLineChartViewBase *)chart; @end // YAxisValueFormatter.m // Copyright © 2018 Anton Komir. All rights reserved. // #import "YAxisValueFormatter.h" @implementation YAxisValueFormatter { NSArray *months; __weak BarLineChartViewBase *_chart; } - (id)initForChart:(BarLineChartViewBase *)chart { self = [super init]; if (self) { self->_chart = chart; } return self; } - (NSString *)stringForValue:(double)value axis:(ChartAxisBase *)axis { int maxLenght = 7; NSString *result = [NSString stringWithFormat:@"%i", (int)value]; int valueLenght = [result length]; int difference = maxLenght - valueLenght; for (int i = 0; i < difference; i++) { result = [NSString stringWithFormat:@" %@", result]; } return result; } @endI know that not the best solution.
thank you!
@wwwang89
just try
leftAxis.labelPosition = .insideChart
or
rightAxis.labelPosition = .insideChart
learn from https://github.com/danielgindi/Charts/issues/3145#issuecomment-355507291
@wwwang89
just try
leftAxis.labelPosition = .insideChart
or
rightAxis.labelPosition = .insideChartlearn from #3145 (comment)
This is a beautiful and simple solution. Proves that the sizing of the chart labels is the problem.
I'll eventually look to keep the labels at a constant size but for now this is a quick fix, thanks.
It seems like setting the label formatter to constant length output would work only for monospaced font labels. For normal fonts it will probably work most of the time but it's not guaranteed...
Update: I have another fix which involves overriding the YAxis class. Unfortunately the yAxis in chart view is protected so I had to modify the library to make that public and settable. Works perfectly. While doing that I also found a way to increase scroll performance as label width calculations are concerned.
The base package is extremely inefficient as it runs all axis labels through a formatter, then finds the longest string, then uses that to calculate the required width. On a normal decimal axis as per default, however, the longest string is always the first or last element in the entries list so it needs to do that only once. Also the width only changes when there's a significant change in the order of magnitude of the axis range - applying all this, one can remove about 999 out of 1000 calls into string formatting and sizing. For all practical purposes the width is never recalculated during scrolling.
Most helpful comment
@wwwang89
just try
leftAxis.labelPosition = .insideChart
or
rightAxis.labelPosition = .insideChart
learn from https://github.com/danielgindi/Charts/issues/3145#issuecomment-355507291