在饼图和条形图中,过度拥挤的标签是不可读的

时间:2016-01-19 16:26:19

标签: ios objective-c charts ios-charts

对于PieCharts,通常有几个“切片”具有非常小的数据部分(例如,<2%),因此,标签彼此重叠并且不可读,如下所示。有谁知道这方面的解决方案?我已经看到一些图表显示了馅饼外面的标签,并指向相应的部分,但我不确定ios-charts是否有类似的东西。

enter image description here

条形图也会出现类似问题,其中所有值彼此重叠并变得不可读,如下所示。我能想到的解决方案是仅显示条形的一个子集,如果用户平移则显示其他条形。

enter image description here

如果有人处理过这两个问题,我会很高兴看到你如何解决它,或者是否更好地使用不同的库。我在下面发布了一些代码,但不确定它是否会有所帮助,因为这可能不是一个实现错误。

条形图

    //...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];

饼图

//初始饼图..     _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];

2 个答案:

答案 0 :(得分:0)

基本上,您可以计算视图中的中间点(或CALayer,无论使用什么)并绘制文本,正确缩放图形:

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];

答案 1 :(得分:0)

首先,我建议在github页面上提交一个问题,并使用ChartsDemo提供示例代码来重现。我试过了,我确实看到了小的重叠,但是如果小条继续变小,则不会绘制值。所以问题在于粒度。

是否绘制文字基于:

internal func passesCheck() -> Bool
{
    guard let dataProvider = dataProvider, barData = dataProvider.barData else { return false }

    return CGFloat(barData.yValCount) < CGFloat(dataProvider.maxVisibleValueCount) * viewPortHandler.scaleX
}

如果数值过多,则不会抽奖;但对你来说似乎没有足够的粒度。

有办法解决它,例如条形图,你可以计算文字宽度,并将其与条形像素宽度进行比较,以确定是否绘制文字。您可以在drawValues中覆盖,或者如果您需要匆忙解决它。饼图类似。

像:

// 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
}