Render a line graph on Apple Watch using watchOS 2

前端 未结 5 1116
说谎
说谎 2021-02-01 11:13

I am trying to render a line/step graph on Apple Watch using watchOS 2. Unlike iOS 9, watchOS 2 doesn\'t support Quartz. It only supports Core Graphics. I tried writing some cod

相关标签:
5条回答
  • 2021-02-01 11:22

    Graph render is done by the help of bezierPath and which is converted to image to attached to Apple Watch

    //Swift-3 Xcode-8.1

    import UIKit class InterfaceController: WKInterfaceController {

    @IBOutlet var graphImage: WKInterfaceImage!
    override func awake(withContext context: Any?) {
        super.awake(withContext: context)
    
        // Configure interface objects here.
    }
    override func willActivate() {
    
        super.willActivate()
        let path = createBeizePath()
    
        //Change graph to image
        let image:UIImage = UIImage.shapeImageWithBezierPath(bezierPath: path, fillColor: .red, strokeColor: .black)
        graphImage.setImage(uiimage)
    }
    
    //Draw graph here
    func createBeizePath() -> UIBezierPath
    {
        let path = UIBezierPath()
        //Rectangle path Trace
        path.move(to: CGPoint(x: 20, y: 100) )
        path.addLine(to: CGPoint(x: 50 , y: 100))
        path.addLine(to: CGPoint(x: 50, y: 150))
        path.addLine(to: CGPoint(x: 20, y: 150))
        return path
      }
    }
    
    extension UIImage {
            class func shapeImageWithBezierPath(bezierPath: UIBezierPath, fillColor: UIColor?, strokeColor: UIColor?, strokeWidth: CGFloat = 0.0) -> UIImage! {
                bezierPath.apply(CGAffineTransform(translationX: -bezierPath.bounds.origin.x, y: -bezierPath.bounds.origin.y ) )
                let size = CGSize(width: 100    , height: 100)
                UIGraphicsBeginImageContext(size)
                let context = UIGraphicsGetCurrentContext()
                var image = UIImage()
                if let context  = context {
                    context.saveGState()
                    context.addPath(bezierPath.cgPath)
                    if strokeColor != nil {
                        strokeColor!.setStroke()
                        context.setLineWidth(strokeWidth)
                    } else { UIColor.clear.setStroke() }
                    fillColor?.setFill()
                    context.drawPath(using: .fillStroke)
                     image = UIGraphicsGetImageFromCurrentImageContext()!
                    context.restoreGState()
                    UIGraphicsEndImageContext()
                }
                return image
            }
        }
    
    0 讨论(0)
  • 2021-02-01 11:24

    Here's code in watchOS 3

      // Create a graphics context
            let size = CGSize(width:self.contentFrame.size.width, height:100)
    
    
            UIGraphicsBeginImageContext(size)
            let context = UIGraphicsGetCurrentContext()
    
            // Setup for the path appearance
            context!.setStrokeColor(UIColor.white.cgColor)
            context!.setLineWidth(4.0)
    
            // Draw lines
            context!.beginPath ();
    
            context?.move(to: CGPoint())
            context?.addLine(to: CGPoint(x: 100, y: 100))
            context?.addLine(to: CGPoint(x: 0, y: 100))
            context?.addLine(to: CGPoint(x: 100, y: 0))
    
            context!.strokePath();
    
            // Convert to UIImage
            let cgimage = context!.makeImage();
            let uiimage = UIImage(cgImage: cgimage!)
    
            // End the graphics context
            UIGraphicsEndImageContext()
    
            self.graphGroup.setBackgroundImage(uiimage)
    
    0 讨论(0)
  • 2021-02-01 11:26

    Here's the example project that shows how to do dynamic graphs on WatchKit 2.0

    https://github.com/vlm/ExampleWatchGraph

    The gist of it is in the GraphPainter.swift file, where CoreGraphics is used to draw into an off-screen buffer (as @shu223 suggested), then display this buffer in a WKInterfaceImage.

    Animated Watch Interface GIF.

    0 讨论(0)
  • 2021-02-01 11:35

    I succeeded to render lines with following steps:

    • Create a bitmap-based graphics context and makes it the current context using UIGraphicsBeginImageContext.
    • Draw into the context.
    • Extract CGImageRef from the context and convert it to UIImage object.
    • Show the image on WKInterfaceGroup or WKInterfaceImage.

    Code:

    // Create a graphics context
    let size = CGSizeMake(100, 100)
    UIGraphicsBeginImageContext(size)
    let context = UIGraphicsGetCurrentContext()
    
    // Setup for the path appearance
    CGContextSetStrokeColorWithColor(context, UIColor.whiteColor().CGColor)
    CGContextSetLineWidth(context, 4.0)
    
    // Draw lines
    CGContextBeginPath (context);
    CGContextMoveToPoint(context, 0, 0);
    CGContextAddLineToPoint(context, 100, 100);
    CGContextMoveToPoint(context, 0, 100);
    CGContextAddLineToPoint(context, 100, 0);
    CGContextStrokePath(context);
    
    // Convert to UIImage
    let cgimage = CGBitmapContextCreateImage(context);
    let uiimage = UIImage(CGImage: cgimage!)
    
    // End the graphics context
    UIGraphicsEndImageContext()
    
    // Show on WKInterfaceImage
    image.setImage(uiimage)
    

    image is WKInterfaceImage property. It works for me.

    Also I can draw using UIBezierPath on watchOS as follow:

    // Create a graphics context
    let size = CGSizeMake(100, 100)
    UIGraphicsBeginImageContext(size)
    let context = UIGraphicsGetCurrentContext()
    UIGraphicsPushContext(context!)
    
    // Setup for the path appearance
    UIColor.greenColor().setStroke()
    UIColor.whiteColor().setFill()
    
    // Draw an oval
    let rect = CGRectMake(2, 2, 96, 96)
    let path = UIBezierPath(ovalInRect: rect)
    path.lineWidth = 4.0
    path.fill()
    path.stroke()
    
    // Convert to UIImage
    let cgimage = CGBitmapContextCreateImage(context);
    let uiimage = UIImage(CGImage: cgimage!)
    
    // End the graphics context
    UIGraphicsPopContext()
    UIGraphicsEndImageContext()
    
    image.setImage(uiimage)
    

    You can check the sample codes here.

    0 讨论(0)
  • 2021-02-01 11:43

    The context here are not CGContext, thus you have the issue. I do not think you can use Core Graphics directly on Apple Watch.

    0 讨论(0)
提交回复
热议问题