图表:仅在条内点击时获取选定的条数据
Charts: Get selected bar data only when tapped inside the bar
我在项目中使用了 https://github.com/danielgindi/Charts 库。
它运行良好,但我只想在用户点击栏内时选择栏数据。
目前,它也会 return 在点击外的栏数据。
当用户点击栏外时,它提供距离点击最近的栏数据。
我这样设置条形图:
_chartView.delegate = self;
_chartView.drawBarShadowEnabled = NO;
_chartView.drawValueAboveBarEnabled = YES;
_chartView.maxVisibleValueCount = 60;
ChartXAxis *xAxis = _chartView.xAxis;
xAxis.labelPosition = XAxisLabelPositionBottom;
xAxis.labelTextColor = [UIColor whiteColor];
xAxis.labelFont = [UIFont systemFontOfSize:20.f];
xAxis.drawGridLinesEnabled = NO;
xAxis.spaceBetweenLabels = 2.0;
xAxis.labelWidth = 100;
ChartYAxis *leftAxis = _chartView.leftAxis;
leftAxis.labelFont = [UIFont systemFontOfSize:20.f];
leftAxis.labelCount = 5;
leftAxis.labelTextColor = [UIColor whiteColor];
leftAxis.valueFormatter = [[NSNumberFormatter alloc] init];
leftAxis.valueFormatter.maximumFractionDigits = 1;
leftAxis.valueFormatter.negativeSuffix = @"k";
leftAxis.valueFormatter.positiveSuffix = @"k";
leftAxis.valueFormatter.positivePrefix = @"$";
leftAxis.valueFormatter.negativePrefix = @"$";
leftAxis.labelPosition = YAxisLabelPositionOutsideChart;
leftAxis.spaceTop = 0.15;
leftAxis.customAxisMin = 0.0; // this replaces startAtZero = YES
_chartView.legend.position = ChartLegendPositionBelowChartLeft;
_chartView.legend.form = ChartLegendFormSquare;
_chartView.legend.formSize = 20.0;
_chartView.legend.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.f];
_chartView.legend.xEntrySpace = 4.0;
_chartView.legend.textColor = [UIColor whiteColor];
NSMutableArray *xVals = [[NSMutableArray alloc] init];
for (int i = 0; i < 12; i++)
{
[xVals addObject:months[i % 12]];
}
NSMutableArray *yVals = [[NSMutableArray alloc] init];
NSMutableArray *yValsColor = [[NSMutableArray alloc] init];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:10 xIndex:1]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:15 xIndex:2]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:20 xIndex:3]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:45 xIndex:4]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:30 xIndex:5]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:5 xIndex:6]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:15 xIndex:7]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:22 xIndex:8]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:32 xIndex:9]];
[yValsColor addObject:[UIColor yellowColor]];
BarChartDataSet *set1 = [[BarChartDataSet alloc] initWithYVals:yVals label:@"Charges"];
set1.barSpace = 0.35;
set1.colors = yValsColor;
NSMutableArray *dataSets = [[NSMutableArray alloc] init];
[dataSets addObject:set1];
BarChartData *data = [[BarChartData alloc] initWithXVals:xVals dataSets:dataSets];
[data setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:20.f]];
[data setValueTextColor:[UIColor whiteColor]];
_chartView.data = data;
NSArray *arrLabelData = [NSArray arrayWithObjects:@"All", @"1/1/2016 to 9/29/2016", @"All", @"All", @"Date of Billed",nil];
NSArray *arrLabel = [NSArray arrayWithObjects:@"Ins:",@" DOS:",@" Location:",@" Provider:",@" Aging Calculation Based On:",nil];
NSMutableAttributedString *strFS = [[NSMutableAttributedString alloc] init];
UIColor *color = [UIColor yellowColor]; // select needed color
NSDictionary *attrs = @{ NSForegroundColorAttributeName : color};
NSDictionary *attrsLab = @{ NSForegroundColorAttributeName : [UIColor whiteColor]};
for(int i = 0; i <arrLabelData.count; i++)
{
NSString *strLabData = [arrLabelData objectAtIndex:i];
NSString *strLab = [arrLabel objectAtIndex:i];
NSAttributedString *attStringLab = [[NSAttributedString alloc] initWithString:strLab attributes:attrsLab];
NSAttributedString *attStringLabData = [[NSAttributedString alloc] initWithString:strLabData attributes:attrs];
[strFS appendAttributedString:attStringLab];
[strFS appendAttributedString:attStringLabData];
}
lblAttributes.attributedText = strFS;
我只想在用户点击栏内时响应数据。
任何人有想法吗?请帮助我
在此先感谢。
我有一个具有相同库的项目,通过将 ChartHighlighter.swift 文件中的 getHighlight 函数更改为以下内容,我能够获得您所要求的功能:
/// Returns a Highlight object corresponding to the given x- and y- touch positions in pixels.
/// - parameter x:
/// - parameter y:
/// - returns:
public func getHighlight(x x: CGFloat, y: CGFloat) -> ChartHighlight?
{
print("y: \(y)")
let xIndex = getXIndex(x)
guard let
selectionDetail = getSelectionDetail(xIndex: xIndex, y: y, dataSetIndex: nil)
else { return nil }
print("selectionDetail: \(selectionDetail.y)")
if(y<selectionDetail.y) {
return nil
}
else {
return ChartHighlight(xIndex: xIndex, value: selectionDetail.value, dataIndex: selectionDetail.dataIndex, dataSetIndex: selectionDetail.dataSetIndex, stackIndex: -1)
}
}
我的应用程序中有用户版本 2.2.3 的图表。试试这个实现来解决您的问题
1) 将函数添加到您的 ChartHighlighter.swift 文件。
public func getBarBounds(e: BarChartDataEntry) -> CGRect
{
guard let
set = self.chart?._data?.getDataSetForEntry(e) as? IBarChartDataSet
else { return CGRectNull }
let barspace = set.barSpace
let y = CGFloat(e.value)
let x = CGFloat(e.xIndex)
let barWidth: CGFloat = 0.5
let spaceHalf = barspace / 2.0
let left = x - barWidth + spaceHalf
let right = x + barWidth - spaceHalf
let top = y >= 0.0 ? y : 0.0
let bottom = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
self.chart?.getTransformer(ChartYAxis.AxisDependency.Left).rectValueToPixel(&bounds)
return bounds
}
2) 更新 ChartHighlighter.swift 文件中的 getHighlight 函数。
public func getHighlight(x x: Double, y: Double) -> ChartHighlight?
{
let xIndex = getXIndex(x)
if (xIndex == -Int.max)
{
return nil
}
let dataSetIndex = getDataSetIndex(xIndex: xIndex, x: x, y: y)
if (dataSetIndex == -Int.max)
{
return nil
}
//Modification for only Bar Selection
let dataSet = self.chart!.data!.getDataSetByIndex(dataSetIndex)
let e = dataSet.entryForXIndex(xIndex) as! BarChartDataEntry!
let rectData = getBarBounds(e)
let point = CGPoint(x: x,y: y)
let isPointInFrame = CGRectContainsPoint(rectData, point)
if (!isPointInFrame)
{
return nil
}
//Modification for only Bar Selection
return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex)
}
希望对您有所帮助。快乐编码...
最大高亮距离 属性 可用于图表视图,默认值为 500 dp。将其更改为 10 并检查您的视图
我将@rohit Sidpara 的回答转换为 3.2.1 版图表
两个函数都需要写在BarHighlighter.swift文件
open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
{
guard
let barData = (self.chart as? BarChartDataProvider)?.barData,
let high = super.getHighlight(x: x, y: y)
else { return nil }
let pos = getValsForTouch(x: x, y: y)
if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet,
set.isStacked
{
return getStackedHighlight(high: high,
set: set,
xValue: Double(pos.x),
yValue: Double(pos.y))
}
else
{
let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet
let entry = set?.entryForIndex(Int(high.x)) as! BarChartDataEntry
let rectOfData = getBarBounds(e: entry)
return rectOfData.contains(CGPoint(x: x, y: y)) ? high: nil
}
}
public func getBarBounds(e: BarChartDataEntry) -> CGRect
{
guard
let dataProvider = self.chart as? BarChartDataProvider
else { return CGRect.null }
let barspace = CGFloat((dataProvider.barData?.barWidth)!) / 2.0
let y = CGFloat(e.y)
let x = CGFloat(e.x)
let barWidth: CGFloat = 0.5
let spaceHalf = barspace / 2.0
let left = x - barWidth + spaceHalf
let right = x + barWidth - spaceHalf
let top = y >= 0.0 ? y : 0.0
let bottom = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
dataProvider.getTransformer(forAxis: YAxis.AxisDependency.left).rectValueToPixel(&bounds)
return bounds
}
我在项目中使用了 https://github.com/danielgindi/Charts 库。
它运行良好,但我只想在用户点击栏内时选择栏数据。
目前,它也会 return 在点击外的栏数据。
当用户点击栏外时,它提供距离点击最近的栏数据。
我这样设置条形图:
_chartView.delegate = self;
_chartView.drawBarShadowEnabled = NO;
_chartView.drawValueAboveBarEnabled = YES;
_chartView.maxVisibleValueCount = 60;
ChartXAxis *xAxis = _chartView.xAxis;
xAxis.labelPosition = XAxisLabelPositionBottom;
xAxis.labelTextColor = [UIColor whiteColor];
xAxis.labelFont = [UIFont systemFontOfSize:20.f];
xAxis.drawGridLinesEnabled = NO;
xAxis.spaceBetweenLabels = 2.0;
xAxis.labelWidth = 100;
ChartYAxis *leftAxis = _chartView.leftAxis;
leftAxis.labelFont = [UIFont systemFontOfSize:20.f];
leftAxis.labelCount = 5;
leftAxis.labelTextColor = [UIColor whiteColor];
leftAxis.valueFormatter = [[NSNumberFormatter alloc] init];
leftAxis.valueFormatter.maximumFractionDigits = 1;
leftAxis.valueFormatter.negativeSuffix = @"k";
leftAxis.valueFormatter.positiveSuffix = @"k";
leftAxis.valueFormatter.positivePrefix = @"$";
leftAxis.valueFormatter.negativePrefix = @"$";
leftAxis.labelPosition = YAxisLabelPositionOutsideChart;
leftAxis.spaceTop = 0.15;
leftAxis.customAxisMin = 0.0; // this replaces startAtZero = YES
_chartView.legend.position = ChartLegendPositionBelowChartLeft;
_chartView.legend.form = ChartLegendFormSquare;
_chartView.legend.formSize = 20.0;
_chartView.legend.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.f];
_chartView.legend.xEntrySpace = 4.0;
_chartView.legend.textColor = [UIColor whiteColor];
NSMutableArray *xVals = [[NSMutableArray alloc] init];
for (int i = 0; i < 12; i++)
{
[xVals addObject:months[i % 12]];
}
NSMutableArray *yVals = [[NSMutableArray alloc] init];
NSMutableArray *yValsColor = [[NSMutableArray alloc] init];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:10 xIndex:1]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:15 xIndex:2]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:20 xIndex:3]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:45 xIndex:4]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:30 xIndex:5]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:5 xIndex:6]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:15 xIndex:7]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:22 xIndex:8]];
[yVals addObject:[[BarChartDataEntry alloc] initWithValue:32 xIndex:9]];
[yValsColor addObject:[UIColor yellowColor]];
BarChartDataSet *set1 = [[BarChartDataSet alloc] initWithYVals:yVals label:@"Charges"];
set1.barSpace = 0.35;
set1.colors = yValsColor;
NSMutableArray *dataSets = [[NSMutableArray alloc] init];
[dataSets addObject:set1];
BarChartData *data = [[BarChartData alloc] initWithXVals:xVals dataSets:dataSets];
[data setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:20.f]];
[data setValueTextColor:[UIColor whiteColor]];
_chartView.data = data;
NSArray *arrLabelData = [NSArray arrayWithObjects:@"All", @"1/1/2016 to 9/29/2016", @"All", @"All", @"Date of Billed",nil];
NSArray *arrLabel = [NSArray arrayWithObjects:@"Ins:",@" DOS:",@" Location:",@" Provider:",@" Aging Calculation Based On:",nil];
NSMutableAttributedString *strFS = [[NSMutableAttributedString alloc] init];
UIColor *color = [UIColor yellowColor]; // select needed color
NSDictionary *attrs = @{ NSForegroundColorAttributeName : color};
NSDictionary *attrsLab = @{ NSForegroundColorAttributeName : [UIColor whiteColor]};
for(int i = 0; i <arrLabelData.count; i++)
{
NSString *strLabData = [arrLabelData objectAtIndex:i];
NSString *strLab = [arrLabel objectAtIndex:i];
NSAttributedString *attStringLab = [[NSAttributedString alloc] initWithString:strLab attributes:attrsLab];
NSAttributedString *attStringLabData = [[NSAttributedString alloc] initWithString:strLabData attributes:attrs];
[strFS appendAttributedString:attStringLab];
[strFS appendAttributedString:attStringLabData];
}
lblAttributes.attributedText = strFS;
我只想在用户点击栏内时响应数据。
任何人有想法吗?请帮助我
在此先感谢。
我有一个具有相同库的项目,通过将 ChartHighlighter.swift 文件中的 getHighlight 函数更改为以下内容,我能够获得您所要求的功能:
/// Returns a Highlight object corresponding to the given x- and y- touch positions in pixels.
/// - parameter x:
/// - parameter y:
/// - returns:
public func getHighlight(x x: CGFloat, y: CGFloat) -> ChartHighlight?
{
print("y: \(y)")
let xIndex = getXIndex(x)
guard let
selectionDetail = getSelectionDetail(xIndex: xIndex, y: y, dataSetIndex: nil)
else { return nil }
print("selectionDetail: \(selectionDetail.y)")
if(y<selectionDetail.y) {
return nil
}
else {
return ChartHighlight(xIndex: xIndex, value: selectionDetail.value, dataIndex: selectionDetail.dataIndex, dataSetIndex: selectionDetail.dataSetIndex, stackIndex: -1)
}
}
我的应用程序中有用户版本 2.2.3 的图表。试试这个实现来解决您的问题
1) 将函数添加到您的 ChartHighlighter.swift 文件。
public func getBarBounds(e: BarChartDataEntry) -> CGRect
{
guard let
set = self.chart?._data?.getDataSetForEntry(e) as? IBarChartDataSet
else { return CGRectNull }
let barspace = set.barSpace
let y = CGFloat(e.value)
let x = CGFloat(e.xIndex)
let barWidth: CGFloat = 0.5
let spaceHalf = barspace / 2.0
let left = x - barWidth + spaceHalf
let right = x + barWidth - spaceHalf
let top = y >= 0.0 ? y : 0.0
let bottom = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
self.chart?.getTransformer(ChartYAxis.AxisDependency.Left).rectValueToPixel(&bounds)
return bounds
}
2) 更新 ChartHighlighter.swift 文件中的 getHighlight 函数。
public func getHighlight(x x: Double, y: Double) -> ChartHighlight?
{
let xIndex = getXIndex(x)
if (xIndex == -Int.max)
{
return nil
}
let dataSetIndex = getDataSetIndex(xIndex: xIndex, x: x, y: y)
if (dataSetIndex == -Int.max)
{
return nil
}
//Modification for only Bar Selection
let dataSet = self.chart!.data!.getDataSetByIndex(dataSetIndex)
let e = dataSet.entryForXIndex(xIndex) as! BarChartDataEntry!
let rectData = getBarBounds(e)
let point = CGPoint(x: x,y: y)
let isPointInFrame = CGRectContainsPoint(rectData, point)
if (!isPointInFrame)
{
return nil
}
//Modification for only Bar Selection
return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex)
}
希望对您有所帮助。快乐编码...
最大高亮距离 属性 可用于图表视图,默认值为 500 dp。将其更改为 10 并检查您的视图
我将@rohit Sidpara 的回答转换为 3.2.1 版图表
两个函数都需要写在BarHighlighter.swift文件
open override func getHighlight(x: CGFloat, y: CGFloat) -> Highlight?
{
guard
let barData = (self.chart as? BarChartDataProvider)?.barData,
let high = super.getHighlight(x: x, y: y)
else { return nil }
let pos = getValsForTouch(x: x, y: y)
if let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet,
set.isStacked
{
return getStackedHighlight(high: high,
set: set,
xValue: Double(pos.x),
yValue: Double(pos.y))
}
else
{
let set = barData.getDataSetByIndex(high.dataSetIndex) as? IBarChartDataSet
let entry = set?.entryForIndex(Int(high.x)) as! BarChartDataEntry
let rectOfData = getBarBounds(e: entry)
return rectOfData.contains(CGPoint(x: x, y: y)) ? high: nil
}
}
public func getBarBounds(e: BarChartDataEntry) -> CGRect
{
guard
let dataProvider = self.chart as? BarChartDataProvider
else { return CGRect.null }
let barspace = CGFloat((dataProvider.barData?.barWidth)!) / 2.0
let y = CGFloat(e.y)
let x = CGFloat(e.x)
let barWidth: CGFloat = 0.5
let spaceHalf = barspace / 2.0
let left = x - barWidth + spaceHalf
let right = x + barWidth - spaceHalf
let top = y >= 0.0 ? y : 0.0
let bottom = y <= 0.0 ? y : 0.0
var bounds = CGRect(x: left, y: top, width: right - left, height: bottom - top)
dataProvider.getTransformer(forAxis: YAxis.AxisDependency.left).rectValueToPixel(&bounds)
return bounds
}