Search code examples
iosswiftuibezierpath

Animating UIBezier to get a live curve


I am trying to create a simple line graph which is being updated live. Some kind of seismograph .

I was thinking about UIBezierPath, by only moving a point on the y-axis according to an input var, I can create a line moving on the time axis.

The problem is that you have to "push" the previous points to free up space for the new ones (so the graph goes from left to right).

What can I try next?

 var myBezier = UIBezierPath()
        myBezier.moveToPoint(CGPoint(x: 0, y: 0))
        myBezier.addLineToPoint(CGPoint(x: 100, y: 0))
        myBezier.addLineToPoint(CGPoint(x: 50, y: 100))
        myBezier.closePath()
        UIColor.blackColor().setStroke()
        myBezier.stroke()

Solution

  • You're correct: you need to push the previous points. Either divide the total width of the graph so it becomes increasingly scaled but retains all data, or drop the first point each time you add a new one to the end. You'll need to store an array of these points and recreate the path each time. Something like:

    //Given...
    let graphWidth: CGFloat = 50
    let graphHeight: CGFloat = 20
    var values: [CGFloat] = [0, 4, 3, 2, 6]
    
    //Here's how you make your curve...
    var myBezier = UIBezierPath()
    myBezier.moveToPoint(CGPoint(x: 0, y: values.first!))
    for (index, value) in values.enumerated() {
        let point = CGPoint(x: CGFloat(index)/CGFloat(values.count) * graphWidth, y: value/values.max()! * graphHeight)
        myBezier.addLineToPoint(point)
    }
    UIColor.blackColor().setStroke()
    myBezier.stroke()
    
    //And here's how you'd add a point...
    values.removeFirst() //do this if you want to scroll rather than squish
    values.append(8)