Crowded shortcuts cannot be read in piechart and barcharts

For PieCharts, there are often several “slices” with a very small fraction of the data (for example, 2%, for example), and as a result, the labels overlap and are not read, as shown below. Does anyone know of this solution? I saw several diagrams that show a label outside the pie and point to the corresponding fragment, but I'm not sure if something like this is possible for ios diagrams.

enter image description here

A similar problem arises for histograms in which all values ​​overlap and become unreadable, as shown below. The solution I can think of would be to display only a subset of the bars and show other columns if the user clicks.

enter image description here

If anyone is dealing with any problem, I would be glad to see how you solved it, or it is better to use another library. I have posted the code below, but am not sure if it will help, as this is apparently not an implementation error.

Chart table

//...init view... _chartView.delegate = self; _chartView.descriptionText = @""; _chartView.noDataTextDescription = @"No data"; _chartView.drawHighlightArrowEnabled = true; _chartView.drawValueAboveBarEnabled = YES; _chartView.drawMarkers = true; _chartView.dragEnabled = true; ChartXAxis *xAxis = _chartView.xAxis; xAxis.labelPosition = XAxisLabelPositionBottom; xAxis.labelFont = [UIFont systemFontOfSize:10.f]; xAxis.drawGridLinesEnabled = NO; xAxis.spaceBetweenLabels = 2.0; ChartYAxis *rightAxis = _chartView.rightAxis; rightAxis.enabled = NO; NSMutableArray *yVals = [[NSMutableArray alloc] init]; NSMutableArray *xVals = [[NSMutableArray alloc] init]; //populate xVals and yVals with data.. BarChartDataSet *set1 = [[BarChartDataSet alloc] initWithYVals:yVals label:@"Occurences"]; set1.colors = ChartColorTemplates.vordiplom; set1.drawValuesEnabled = YES; NSMutableArray *dataSets = [[NSMutableArray alloc] init]; [dataSets addObject:set1]; BarChartData *bdata = [[BarChartData alloc] initWithXVals:xVals dataSets:dataSets]; [bdata setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:10.f]]; _chartView.data = bdata; [self.view addSubview:_chartView]; 

Pie chart

// init pie chart .. _pieChart.delegate = self;

 _pieChart.usePercentValuesEnabled = YES; _pieChart.descriptionText = @""; _pieChart.drawCenterTextEnabled = YES; NSMutableArray *yVals = [[NSMutableArray alloc] init]; NSMutableArray *xVals = [[NSMutableArray alloc] init]; //...populate xVals and yVals with data PieChartDataSet *dataSet = [[PieChartDataSet alloc] initWithYVals:yVals label:@"Locations"]; dataSet.sliceSpace = 2.0; dataSet.colors = ChartColorTemplates.joyful; PieChartData *data1 = [[PieChartData alloc] initWithXVals:xVals dataSet:dataSet]; NSNumberFormatter *pFormatter = [[NSNumberFormatter alloc] init]; pFormatter.numberStyle = NSNumberFormatterPercentStyle; pFormatter.maximumFractionDigits = 1; pFormatter.multiplier = @1.f; pFormatter.percentSymbol = @" %"; [data1 setValueFormatter:pFormatter]; _pieChart.data = data1; [self.view addSubview:_pieChart]; 
+5
source share
2 answers

First, I suggest pointing out the problem on the github page and providing sample code using ChartsDemo to play. I tried this and I see a slight overlap, but if the bars last less, then the value will not be drawn. Therefore, the problem is granularity.

Is it possible to draw text based on:

 internal func passesCheck() -> Bool { guard let dataProvider = dataProvider, barData = dataProvider.barData else { return false } return CGFloat(barData.yValCount) < CGFloat(dataProvider.maxVisibleValueCount) * viewPortHandler.scaleX } 

If there are too many values, they will not be drawn; But for you this seems insufficient.

There are ways to solve this problem, for example, a histogram, you can calculate the width of the text and compare it with the width of the pixel bar to determine whether to draw text or not. You can override in drawValues or if you need to solve it quickly. Pie chart is similar.

how

 // calculate bar pixel width let barWidth: CGFloat = 0.5 let barSpaceHalf = dataSet.barSpace / 2.0 let left = 0 - barWidth + barSpaceHalf let right = 0 + barWidth - barSpaceHalf var leftPoint = CGPoint(x: left, y: 0) var rightPoint = CGPoint(x: right, y: 0) trans.pointValueToPixel(&leftPoint) trans.pointValueToPixel(&rightPoint) let barPixelWidth = rightPoint.x - leftPoint.x let valueTextWidth = valueText.sizeWithAttributes([NSFontAttributeName: valueFont]).width if valueTextWidth < barPixelWidth { // draw text } 
0
source

Basically, you could calculate the midpoint on your view (or CALayer, no matter what is used) and draw the text correctly scaled for the shape:

 NSString *dataString = [[NSString alloc] initWithFormat:@"Some data"]; CGPoint centerPoint = CGPointMake(self.bounds.origin.x + self.bounds.size.width / 2, self.bounds.origin.y + self.bounds.size.height / 2); CATextLayer *textLayer = [CATextLayer layer]; [textLayer setFont:@"Helvetica-Bold"]; //Scale the font and set proper alignment [textLayer setFontSize:12]; [textLayer setAlignmentMode:kCAAlignmentCenter]; [textLayer setBounds:self.frame]; [textLayer setPosition:centerPoint]; [textLayer setString:dataString]; [self.layer addSublayer:textLayer]; 
0
source

Source: https://habr.com/ru/post/1240936/


All Articles