Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(v3.0 + Swift3.0)ChartView highlightValueWithX not working #1495

Closed
dtogias opened this issue Sep 20, 2016 · 24 comments
Closed

(v3.0 + Swift3.0)ChartView highlightValueWithX not working #1495

dtogias opened this issue Sep 20, 2016 · 24 comments

Comments

@dtogias
Copy link

dtogias commented Sep 20, 2016

ChartView highlightValueWithX method seems to stop working for v3.0 + Swift3.0
Xcode 8/Master branch/Objc.

@liuxuan30 liuxuan30 added the bug label Sep 21, 2016
@danielgindi
Copy link
Collaborator

@PhilJay highlightValue(x...) functions are failing, because the highlight renderer expects a Y value to be present. The outcome is a NaN, which causes it to render nowhere...

@PhilJay
Copy link
Collaborator

PhilJay commented Sep 22, 2016

Both Android and iOS?

@danielgindi
Copy link
Collaborator

Yeah...

@PhilJay
Copy link
Collaborator

PhilJay commented Sep 24, 2016

Hmmm... just looked through the code, this is a tricky one. For the case that we have multiple entries on the same x-position, it won't be possible to successfully highlight a certain entry without any specification of the y-position.

So maybe we should drop this method?
Another option would be to include the y-position in the method (as a parameter)?

@danielgindi
Copy link
Collaborator

Well the problem starts with selection from touch events - it still does not really work, if you have a scatter or bubble charts with multiple values on same x. It actually selects the first or last one on the same x - depending on the position of the touch on the X axis!

After we fix that - I guess out algorithm will know to take a Y value and after reaching the correct X it will start searching for the correct Y.
And then we'll have the option to pass a Y value, as a separate method! :-)
The original one, to highlight simply by an X is very useful and many many people depend on it, judging by the issues... So we'll get hate-mail if we remove that :-)

@apurva
Copy link

apurva commented Sep 25, 2016

Is there any current work around to programmatically highlight a line chart item? Are all the highlight methods broken at the moment?

@liuxuan30
Copy link
Member

@apurva line chart should work just fine. I checked ChartsDemo with latest mater branch

@wacumov
Copy link

wacumov commented Oct 6, 2016

Programmatically highlight still not working in line charts.

I try to highlight the last value:

[self.lineChartView highlightValueWithX:self.lineChartView.chartXMax dataSetIndex:0 callDelegate:YES];

But in delegate method - (void)chartValueSelected:entry:highlight: highlight.xPx and highlight.yPx are NaN.

@apurva
Copy link

apurva commented Oct 6, 2016

I can re-confirm that highlightValueWithX is not working.

I tried creating a highlight
ChartHighlight * high = [[ChartHighlight alloc]initWithX:(double)someInt dataSetIndex:0];
and used the highlightValueWithHighlight method with it but still does not highlight. The chartValueSelected: entry: highlight: delegate method is called, that contains the correct values in the entry object but the highlight object has a NaN in the y value.

Is there any way to create a ChartHighlight * object containing the y value as well? I see various init methods for the ChartHighlight class but all others need absolute pixel positions.

@liuxuan30 Can you point out which part of the charts demo highlights a chart programmatically?

Alternatively, is there a way to show the currently selected entry in any other mechanism besides using highlighting?

This is absolutely essential for TVOS since Charts does not support the focus environment, and user interactions on the chart need to be handled programmatically instead of relying on the built in gesture recognizers.

@ryanschneider
Copy link

To work around this issue I've done the following in my local copy:

In Highlight.swift, add an initializer that takes a y value as well:

    /// - parameter x: the x-value of the highlighted value
    /// - parameter y: the y-value of the highlighted value
    /// - parameter dataSetIndex: the index of the DataSet the highlighted value belongs to
    public init(x: Double, y: Double, dataSetIndex: Int)
    {
        _x = x
        _y = y
        _dataSetIndex = dataSetIndex
    }

Then when I want to programmatically highlight, I do it like so:

   let entry = //... the ChartDataEntry I want to highlight
   self.chart.highlightValue(
       Highlight(x: entry.x, y: entry.y, dataSetIndex: 0)
   )

I'm definitely not familiar enough with the code to know if this is decent approach to move forward with or not. If it is, I think one thing that would help is a ChartData.highlightForEntry() -> Highlight to act as an inverse to ChartData.entryForHighlight()

@ryanschneider
Copy link

Actually, looking closer, I found that there were recent fixes to some of the other renderers that were not applied to Line charts.

In this commit:

8905a46#diff-52d760df99fc778bb8222bd3cc9ce413R225

The x and y variables were changed to come from the entry, not the Highlight h. I think if this same fix was applied to LineChartRenderer the issue would be fixed.

I'll try that out and hopefully get a PR for it ready today time permitting.

@ryanschneider
Copy link

Also, it doesn't look like the y Value is actually used, since the highlight line just goes from contentTop to contentBottom. The root of the issue is actually that in this line:

let pt = trans.pixelForValues(x: x, y: y)

If y is NaN then pt.x comes out as NaN as well. This actually appears to be a Swift 3/CoreGraphics bug, as evidenced in the Swift Repl here:

  7> import CoreGraphics
  8> let trans = CGAffineTransform(scaleX: 1.0, y: 1.0)
trans: CGAffineTransform = {
  a = 1
  b = 0
  c = 0
  d = 1
  tx = 0
  ty = 0
}
  9> let pt = CGPoint(x: 1.0, y: Double.nan)
pt: CGPoint = (x = 1, y = NaN)
 10> pt.applying(trans)
$R2: CGPoint = (x = NaN, y = NaN)

ryanschneider added a commit to ryanschneider/Charts that referenced this issue Oct 6, 2016
… used in `ScatterChartRenderer`.

Fixes ChartsOrg#1495.  I'm not sure if iterating over entries is necessary, or if this can be collapsed to
just a single `set.entryForXValue()` call.
@ryanschneider
Copy link

@apurva can you try my fix-1495 branch here:

https://github.com/ryanschneider/Charts/tree/fix-1495

And see if it works as expected for you? It's working for me. @danielgindi & @liuxuan30, I more or less copied the code from ScatterChartRenderer but added the if x > chartXMax * animator.phaseX check which LineChartRenderer had.

I don't think I need to be iterating over set.entriesForXValue(high.x) but currently am. I don't think there's harm since there should never be more than one entry, but if you can confirm that's the case I'll happily collapse that to a single set.entryForXValue(high.x) call and send a PR.

It'd also be nice to add a programmatic highlight option to the ChartsDemo to aid in regression testing highlight bugs, but I haven't investigated what it'd take to do that.

@liuxuan30
Copy link
Member

Thank you for your efforts @ryanschneider ! @danielgindi what you think?

@apurva
Copy link

apurva commented Oct 10, 2016

@ryanschneider Thanks for your efforts. I tried the changes in your branch, but both the methods highlightValueWithX and highlightValueWithHighlight both still do not work for me. The y value of the highlight is still NaN and the highlight does not draw on the chart when called programmatically.

@apurva
Copy link

apurva commented Oct 10, 2016

@danielgindi Just tested with the latest master, including your commit at 32a5952

highlightValueWithX still does not show the highlight lines. The delegate gets fired and the y value of highlight is still NaN in the delegate. As the case earlier, highlighting via the gesture recognizers show the highlight lines, only not so when highlightValueWithX is called.

@dtogias
Copy link
Author

dtogias commented Nov 28, 2016

Still does not work.

@Paulito240
Copy link

Paulito240 commented Apr 10, 2017

Still not working for me in Swift 3.

`class ChartsViewController: UIViewController {

@IBOutlet var lineChartView: LineChartView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Do any additional setup after loading the view.

    let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
    let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0]
    
    setChart(dataPoints: months, values: unitsSold)
    
}

func setChart(dataPoints: [String], values: [Double]) {
    
    var dataEntries: [ChartDataEntry] = []
    
    for i in 0..<dataPoints.count {
        let dataEntry = ChartDataEntry(x: Double(i), y: values[i])
        dataEntries.append(dataEntry)
    }

    let lineChartDataSet = LineChartDataSet(values: dataEntries, label: "Units Sold")
    let lineChartData = LineChartData(dataSet: lineChartDataSet)
    lineChartDataSet.highlightLineWidth = 2
    lineChartDataSet.highlightColor = UIColor.red
    
    lineChartView.data = lineChartData

    lineChartView.highlightValue(x: 3, dataSetIndex: 0)
    
    }

}`

@jmamegroot
Copy link

Change this line: lineChartView.highlightValue(x: 3, dataSetIndex: 0)

to: lineChartView.highlightValue(Highlight(x: 3, y: 0, dataSetIndex: 0)

@dyeazel
Copy link

dyeazel commented May 1, 2017

I tried specifying a y:0 on a line graph with multiple datasets and it still doesn't work. Is there any update on this? It's a pretty big bug.

I'm calling from Objective C.

@jndefosse
Copy link

jndefosse commented Sep 19, 2017

Little hack to get the position of the highlighted value

// Highlight set programmatically
let dataEntry = dataEntries[linechartData.entryCount-1]
self.lineChartView.highlightValue(Highlight(x:` dataEntry.x, y:dataEntry.y, dataSetIndex: 0), callDelegate:` true)
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
        var markerPosition = CGPoint(x:highlight.xPx, y: highlight.yPx)
        // Hack to get the real position of the highlight programaticaly
        if markerPosition.x.isNaN || markerPosition.y.isNaN{
            let transformer = lineChartView.getTransformer(forAxis: lineChartView.leftAxis.axisDependency)
            let pt = transformer.pixelForValues(x: entry.x, y: entry.y)
            markerPosition.x = pt.x
            markerPosition.y = pt.y
        }
}

@martaGonz
Copy link

I tried your hack , jndefosse, but how can I call the function to show the labels only when entry is highlighted?

@shruti1512
Copy link

Is this bug fixed? I cannot seem to highlight a section in Pie Chart s of iOS 13.5 Swift 5.1

@pmairoldi
Copy link
Collaborator

Closed by #4721

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests