Open AaronVinh opened 7 years ago
Actually getBarBounds
is not used by the library...
First, where do you set your chartView.data = chartData
? make sure it's after your chart setup or call notifyDataSetChanged()
I compared horizontal bar chart's getBarBounds
and prepareBuffer
, it had a diff, basically getBarBounds
does not handle stacked bar case, and when it's not stacked,
prepareBuffer
is like:
if !containsStacks || vals == nil
{
let bottom = CGFloat(x - barWidthHalf)
let top = CGFloat(x + barWidthHalf)
var right = isInverted
? (y <= 0.0 ? CGFloat(y) : 0)
: (y >= 0.0 ? CGFloat(y) : 0)
var left = isInverted
? (y >= 0.0 ? CGFloat(y) : 0)
: (y <= 0.0 ? CGFloat(y) : 0)
// multiply the height of the rect with the phase
if right > 0
{
right *= CGFloat(phaseY)
}
else
{
left *= CGFloat(phaseY)
}
barRect.origin.x = left
barRect.size.width = right - left
barRect.origin.y = top
barRect.size.height = bottom - top
buffer.rects[bufferIndex] = barRect
bufferIndex += 1
}
vs. getBarBounds
open override func getBarBounds(entry e: BarChartDataEntry) -> CGRect
{
guard
let data = _data as? BarChartData,
let set = data.getDataSetForEntry(e) as? IBarChartDataSet
else { return CGRect.null }
let y = e.y
let x = e.x
let barWidth = data.barWidth
let top = x - 0.5 + barWidth / 2.0
let bottom = x + 0.5 - barWidth / 2.0
let left = y >= 0.0 ? y : 0.0
let right = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds)
return bounds
}
I think it's a bug, but I don't know why there is a method for getting bar bounds.
What you can try is override the method with prepareBuffer
content to see if it fix your issue, or just remove +- 0.5
@danielgindi do you remember why +- 0.5 in horizontal bar chart getBarBounds
? legacy code issue? Seems not necessary right now. Don't see other place do this +- 0.5
@AaronVinh can you help verify, if you just remove +-0.5 in getBarBounds, will it fix your issue? If so, seems we have a simple clean fix for this issue.
After removing the 0.5 the bars appear to be the correct size, but in the wrong place.
After some digging, found out you have to add the isInverted
condition as well.
So yes it's buggy using getBarBounds as it's not the same as what in renderer code. I will check how to make a full fix.
open override func getBarBounds(entry e: BarChartDataEntry) -> CGRect
{
guard
let data = _data as? BarChartData,
let set = data.getDataSetForEntry(e) as? IBarChartDataSet
else { return CGRect.null }
let y = e.y
let x = e.x
let isInverted = self.isInverted(axis: set.axisDependency)
let barWidth = data.barWidth
let top = x + barWidth / 2.0
let bottom = x - barWidth / 2.0
let right = isInverted
? (y <= 0.0 ? y : 0.0)
: (y >= 0.0 ? y : 0.0)
let left = isInverted
? (y >= 0.0 ? y : 0.0)
: (y <= 0.0 ? y : 0.0)
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
getTransformer(forAxis: set.axisDependency).rectValueToPixel(&bounds)
return bounds
}
also, you have to be careful that you must add the layers after the valueToPixelMatrix
is fully initialized. if you just put your code right after something like view.chartData = data
, it will be wrong position.
You can setup a delay like:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
for (int i = 0; i < yVals.count; i++) {
ChartDataEntry *entry = [set1 entryForIndex:i];
if (entry != nil) {
CGRect bound = [_chartView getBarBoundsWithEntry:entry];
CAGradientLayer *layer = [CAGradientLayer layer];
[layer setFrame:bound];
layer.colors = @[(id)[UIColor redColor].CGColor, (id)[UIColor greenColor].CGColor];
layer.startPoint = CGPointMake(0.0, 0.5);
layer.endPoint = CGPointMake(1.0, 0.5);
[_chartView.layer addSublayer:layer];
}
}
});
or set a observer when the matrix is fully set after calling prepareOffsetMatrix
or somewhere, or you just override the renderer code to add the gradient in real time using CoreGraphics (as layers may introduce side effect, I recommend not using CALayer inside the library)
is this possible using CombinedChartView()?
I believe that the getBarBounds function is bugged. I am trying to draw a gradient layer over each bar by grabbing the bounds for each bar. Here is my code `
var chartEntries = [BarChartDataEntry]()
you can see in the screenshot the actualy bars in the light blue color and the gradient layer on top of them. The gradient layers' positions are off as well as the wrong size. Am I misunderstanding how the getBounds functions works or is it bugged?