How to animate only x Axis in core plot? - ios

I am animating x Axis value in core plot but with that my xAxis , yAxis is also animating and disappearing . My set up for graph is shown in here as I have some issue related to graph data I have asked question and here as u can see in code graph set up is correct : Graph set up code. What is missing? MY code for animation is as below:
let plotSpace = graph.defaultPlotSpace as! CPTXYPlotSpace!
let location = currentIndex
let oldRange = CPTPlotRange(location: location , length: kMaxDataPoints - 2)
let newRange = CPTPlotRange(location: location + 1, length: kMaxDataPoints - 2)
CPTAnimation.animate(plotSpace, property: "xRange", fromPlotRange: oldRange, toPlotRange: newRange, duration: 1.0)
currentIndex += 1

(moved from the comments into an answer)
You can use axis constraints to lock the y-axis in position. Look at the "Real Time Plot" in the Plot Gallery example app.

Related

highlightValue not working in chart with CombinedChartView :: Display marker programmatically is not working :: ChartIssue :: iOS Swift :: DanielGindi

Here is what i am doing!
chart.highlightValue(x: timeStampValue, dataSetIndex: totalCount)
==> In the above line,
timeStampValue is x axis value which i have set while filling up the array.
totalCount is total count of array of data which i am displaying in chart.
What i need to achieve is
When chart screen comes up, i need to display marker by default and for that, i am using "highlightValue" method of chart which is not working.
Please let me know the solution to show marker by default programatically.
NOTE: I am using marker whose UI is custom which is working fine when i tap manually at point in chart:
let marker = CustomMarkerView.viewFromXib()!
marker.chartView = chart
chart.marker = marker
chart.drawMarkers = true
Library used : https://github.com/danielgindi/Charts
Chart Data set :
let data = CombinedChartData()
data.lineData = LineChartData(dataSets:[viewModel.lineChartDataSet, viewModel.emptylineChartDataSet])
data.lineData.highlightEnabled = true
viewModel.lineChartDataSet.highlightColor = AssetsColor.highlightedColor.color
viewModel.lineChartDataSet.drawHorizontalHighlightIndicatorEnabled = false
viewModel.lineChartDataSet.highlightLineDashPhase = 2
viewModel.lineChartDataSet.highlightLineDashLengths = [5, 2.5]
you are using the wrong value for dataSetIndex param
based on your code, the datasets only contains 2 data
data.lineData = LineChartData(dataSets:[viewModel.lineChartDataSet, viewModel.emptylineChartDataSet])
dataSetIndex is not data count, in linechart dataset represent a line that has many data (x,y), so dataSetIndex is more like which line
so your code should be something like this
chart.highlightValue(x: timeStampValue, dataSetIndex: 0)
chart.highlightValue(x: timeStampValue, dataSetIndex: 0, dataIndex: 0)
When i added 1 more parameter which is dataIndex as 0 and it worked.
Here, dataSetIndex is set to 0 because it is CombinedChartView where i have merged 2 data set.

CorePlot - Annotations swinging in the Scatter Plot

In my app I've a CorePlot which hosts three scatterplots, I've also configured as follows,
let borderStyle = CPTMutableLineStyle()
borderStyle.lineColor = maxPlotColor
let textLayer = CPTTextLayer(text: "MAX")
textLayer.fill = CPTFill(color: .white())
textLayer.cornerRadius = 10.0
textLayer.borderLineStyle = borderStyle
maxLabelAnnotation = CPTPlotSpaceAnnotation(plotSpace: maxLinePlot.plotSpace!, anchorPlotPoint: [5, NSNumber(value: kMaxLineValue)])
maxLabelAnnotation.contentLayer = textLayer
maxLinePlot.graph?.plotAreaFrame?.plotArea?.addAnnotation(maxLabelAnnotation)
The annotations are updated dynamically when the plot data is updated. The code snippet is shown below,
func newData(_ theTimer: Timer) {
// MARK: Dynmic annotations
maxLabelAnnotation.anchorPlotPoint = [NSNumber(value: currentIndex - 18), NSNumber(value: kMaxLineValue)]
riskLabelAnnotation.anchorPlotPoint = [NSNumber(value: currentIndex - 18), NSNumber(value: kRiskLineValue)] }
The problem is shown in the figure, where the annotation is moving back and froth as the graph moving continuously
I just want to stick the annotation in a position with out any swinging. any help would be much appreciated. Thanks in advance.
The annotations are locked to the plot space as it scrolls, but you update their anchor positions with each new data point, causing them to jump to the next position. Use layer annotations instead of plot space annotations to lock them in place. You'll need to recalculate the y-positions if the scale of the y-axis changes but the labels will stay in place as the graph scrolls below them.
Do this after the view hierarchy is build and everything is laid out so the view calculations are correct.
maxLinePlot.layoutIfNeeded()
if let plotArea = maxLinePlot.graph?.plotAreaFrame?.plotArea {
let plotSpace = maxLinePlot.plotSpace!
let viewPoint = plotSpace.plotAreaViewPoint(forPlotPoint: [0.0, kMaxLineValue])
let maxLabelAnnotation = CPTLayerAnnotation(anchorLayer: plotArea)
maxLabelAnnotation.contentLayer = textLayer
maxLabelAnnotation.xConstraints = CPTConstraints(relativeOffset: 0.25)
maxLabelAnnotation.yConstraints = CPTConstraints(lowerOffset: viewPoint.y)
plotArea.addAnnotation(maxLabelAnnotation)
}

iOS -Chart: Y- Axis interval difference between value

I want to make Y-axis interval with a certain difference. Let's say the multiple of 100 or any fix value, currently it draws with their own interval.
I am sharing my formatting code here.
let leftAxis = chartView.leftAxis
leftAxis.valueFormatter = IntAxisValueFormatter()
leftAxis.granularityEnabled = true
leftAxis.granularity = 1
I am able to solve my challenge, I am adding my fix here. First I calculated the total range then divided them by interval diff and set the LabelCount.
let totalRange = maxY - minY
let interval = 100 //Let's say 100 in my case
leftAxis.setLabelCount(Int(totalRange/interval) + 1, force: true)
One way is you calculate scale value according to your data. And you can use following function to scale as you need. But exact with value difference I don't think it is possible.
self.lineChart.setScaleMinima(1.0, scaleY: 2.0)
In above value first parameter will zoom in horizontally while second will zoom vertically.

iPhone calculate numbers between 0-50 for custom slider

I want to calculate numbers between 0 to 50 when user move on the slider right and left. I am using a formula such as but didn't succedded.
(point.x + 100) / 20
Where point.x is a CGPoint getting with locatioOfView: method between two UIView's
CGPoint point = [sender locationInView:self.viewBaseSlider];
Note : Here self.viewBaseSlider is not a slider it is a Custom View.
Any ideas?
You have to translate location from range between 0 to your-custom-view-width to range from 0 to your-slider-max (50 in this case).
Here's my take on it in swift:
let maxPoints = 50
let customViewWidth = customView.frame.size.width
let pointWidth = Float(customViewWidth) / Float(maxPoints)
if let touch = touches.first {
let location = touch.location(in: customView)
let point = Int(roundf(Float(location.x) / pointWidth))
print("Selected \(point)")
}
And here's working example, where grey area is customView and output in console comes from clicking in the start, around the middle and the end of the grey region:

scatter graph + line graph in ios-Charts

Hi i need a graph as attached for ios. I am using ios-Chart library(swift alternative of MPAndroidChart) for swift .
I have managed to get these points on the graph using the scatter graph. But i couldn't figure out how will i connect the two vertical points. Any help or early response will be appreciate able.
my current code is :
func drawChart(dataPoints:[String] , value1 :[Double] , value2:[Double])
{
var dataEntries1:[ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value:value1[i] , xIndex : i)
dataEntries1.append(dataEntry)
}
var dataEntries2:[ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value:value2[i] , xIndex : i)
dataEntries2.append(dataEntry)
}
let dataSet1 = ScatterChartDataSet(yVals: dataEntries1, label: "Value1" )
dataSet1 .setColor(UIColor.blueColor())
let dataSet2 = ScatterChartDataSet(yVals: dataEntries2 ,label: "Value2")
dataSet2.setColor(UIColor.greenColor())
var bloodPressureDataSets = [ScatterChartDataSet]()
bloodPressureDataSets.append(dataSet1)
bloodPressureDataSets.append(dataSet2)
let barChartData = ScatterChartData(xVals: dataPoints, dataSets: bloodPressureDataSets)
bpChart.xAxis.labelPosition = .Bottom
bpChart.rightAxis.enabled=false
//barChart.legend.enabled=false
bpChart.descriptionText=""
bpChart.data = barChartData
}
Currently i can see this type of graph using the above code.
I want to join these two vertical points like the graph below,
take a look at scatter chart renderer, drawDataSet func. You can connect the dots there
UPDATE towards your comments:
first, go to ScatterChartRenderer and locate to
internal func drawDataSet(context context: CGContext, dataSet: ScatterChartDataSet)
This is where we calculate the position and draw the shape here
There is a main loop:
for (var j = 0, count = Int(min(ceil(CGFloat(entries.count) * _animator.phaseX), CGFloat(entries.count))); j < count; j++)
{
let e = entries[j]
point.x = CGFloat(e.xIndex)
point.y = CGFloat(e.value) * phaseY
point = CGPointApplyAffineTransform(point, valueToPixelMatrix);
...
}
Here's the iteration of the data entries your provide in the dataSet, we just get the xIndex and y value here and convert it to the coordinate on the screen.
So what you can do is to sub class this renderer, override this function to get what you want.
e.g. You want to connect the data entries(the dot) for the same xIndex, you should first iterate each data set to collect all the entries on same xIndex, use CGPointApplyAffineTransform(point, valueToPixelMatrix) to convert and use CoreGraphics APIs to draw the line. You don't need to worry about the math, the library already gives you the API to convert between data value and the screen coordinate value. You just focus on how to draw the chart.

Resources