Search code examples
rubycalayerpie-chartrubymotion

RubyMotion Pie Chart CALayer


I am trying to translate this example http://lepetit-prince.net/ios/?p=1510 into RubyMotion and neither of the 'pie slices' I create show up on screen. I am not using the for loop in the example because I am only using two 'slices' of the pie. Any ideas?

chart = UIView.alloc.initWithFrame(CGRect.new([60, 100], [200, 200]))
chart.backgroundColor = UIColor.colorWithRed(0, green:0, blue:0, alpha:0.5)
chart.layer.cornerRadius = 100
@window.addSubview(chart)

green = 70.0
red = 30.0

red = red / 100.0 * 2.0 * Math::PI
green = green / 100 * 2.0 * Math::PI
start = 0.0

path = UIBezierPath.alloc.init
finish = start + red
sa = start - Math::PI / 2.0
ea = finish - Math::PI / 2.0
puts sa, ea
path.moveToPoint(CGPoint.new(100, 100))
path.addArcWithCenter(CGPoint.new(100, 100), radius:100, startAngle:sa, endAngle:ea, clockwise:true)
sl = CAShapeLayer.alloc.init
sl.fillColor = UIColor.redColor
sl.path = path.CGPath
chart.layer.addSublayer(sl)

start = finish

path = UIBezierPath.alloc.init
finish = start + green
sa = start - Math::PI / 2.0
ea = finish - Math::PI / 2.0
path.moveToPoint(CGPoint.new(100, 100))
path.addArcWithCenter(CGPoint.new(100, 100), radius:100, startAngle:sa, endAngle:ea, clockwise:true)
sl = CAShapeLayer.alloc.init
sl.fillColor = UIColor.greenColor
sl.path = path.CGPath
chart.layer.addSublayer(sl)

mask = UIView.alloc.initWithFrame(CGRect.new([0, 0], [196, 196]))
mask.layer.cornerRadius = 98
mask.center = CGPoint.new(100, 100)
mask.backgroundColor = UIColor.whiteColor

chart.addSubview(mask)

Solution

  • I got your code to work with minor modifications.

    1. The only real bug was that the fill color of a CALayer needs to be a CGColor and not a UIColor. To fix that, I added .CGColor to do the conversion.

    2. I put your code inside of viewDidLoad of a ViewController. Since you didn't provide all of your code, I wasn't sure how you had implemented it.

    3. It isn't necessary to use CGPoint.new and CGRect.new in RubyMotion. I replaced those with simpler direct array constants, such as [100, 100] and [[60, 100], [200, 200]].

    4. I made the mask smaller so that it looked more like the original example.

    Here's the full code:

    app_delegate.rb

    class AppDelegate
      def application(application, didFinishLaunchingWithOptions:launchOptions)
        @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
        @window.rootViewController = ViewController.alloc.init
        @window.makeKeyAndVisible
        true
      end
    end
    

    view_controller.rb

    class ViewController < UIViewController
      def viewDidLoad
        view.backgroundColor = UIColor.whiteColor
    
        chart = UIView.alloc.initWithFrame([[60, 100], [200, 200]])
        chart.backgroundColor = UIColor.colorWithRed(0, green:0, blue:0, alpha:0.5)
        chart.layer.cornerRadius = 100
    
        green = 70.0
        red = 30.0
    
        red = red / 100.0 * 2.0 * Math::PI
        green = green / 100 * 2.0 * Math::PI
        start = 0.0
    
        path = UIBezierPath.alloc.init
        finish = start + red
        sa = start - Math::PI / 2.0
        ea = finish - Math::PI / 2.0
        puts sa, ea
        path.moveToPoint([100, 100])
        path.addArcWithCenter([100, 100], radius:100, startAngle:sa, endAngle:ea, clockwise:true)
        sl = CAShapeLayer.alloc.init
        sl.fillColor = UIColor.redColor.CGColor
        sl.path = path.CGPath
        chart.layer.addSublayer(sl)
    
        start = finish
    
        path = UIBezierPath.alloc.init
        finish = start + green
        sa = start - Math::PI / 2.0
        ea = finish - Math::PI / 2.0
        path.moveToPoint([100, 100])
        path.addArcWithCenter([100, 100], radius:100, startAngle:sa, endAngle:ea, clockwise:true)
        sl = CAShapeLayer.alloc.init
        sl.fillColor = UIColor.greenColor.CGColor
        sl.path = path.CGPath
        chart.layer.addSublayer(sl)
    
        mask = UIView.alloc.initWithFrame([[0, 0], [100, 100]])
        mask.layer.cornerRadius = 50 
        mask.center = [100, 100]
        mask.backgroundColor = UIColor.whiteColor
    
        chart.addSubview(mask)
        view.addSubview(chart)
      end
    end