代码之家  ›  专栏  ›  技术社区  ›  Mahir

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

  •  5
  • Mahir  · 技术社区  · 9 年前

    对于饼图,通常有几个“切片”,数据的一部分很小(例如<2%),因此,标签相互重叠,不可读,如下所示。有人知道解决这个问题的方法吗?我看过一些图表,其中显示了饼图外的标签,并指向相应的部分,但我不确定ios图表是否可能出现类似的情况。

    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=自我;

    _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 回复  |  直到 9 年前
        1
  •  0
  •   Wingzero    9 年前

    首先,我建议在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
    }
    
        2
  •  0
  •   Bretsko Zorayr    9 年前

    基本上,您可以计算视图(或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];