繁体   English   中英

使用watchOS 2在Apple Watch上渲染折线图

[英]Render a line graph on Apple Watch using watchOS 2

我试图使用watchOS 2在Apple Watch上渲染线条/步骤图。与iOS 9不同,watchOS 2不支持Quartz。 它只支持Core Graphics。 我尝试编写一些代码来绘制折线图但我得到一个错误“CG​​ContextRestoreGState:无效的上下文0x0。这是一个严重的错误。这个应用程序,或它使用的库,正在使用无效的上下文,从而有助于整体系统稳定性和可靠性降低。这个通知是礼貌的:请解决这个问题。在即将到来的更新中它将成为一个致命错误。“

以下是我使用的代码:

import WatchKit
import Foundation
import UIKit

class InterfaceController: WKInterfaceController{
    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)
        let path = UIBezierPath()
        let startPoint =  CGPointMake(0.0, 0.0)
        path.moveToPoint(startPoint)
        let nextPoint = CGPointMake(20.0, 20.0)
        path.addLineToPoint(nextPoint)
        path.lineWidth = 1.0
        UIColor.whiteColor().setStroke()
        path.stroke()
    }

    override func willActivate() {
        super.willActivate()

    }

    override func didDeactivate() {
        super.didDeactivate()
    }
}

我的最终结果应该像Apple Watch上的Stocks app一样。 每当用户点击特定股票时,他将能够查看/可视化该股票的统计数据。 任何人都可以帮助我实现这一目标。

我成功地使用以下步骤渲染线条:

  • 创建基于位图的图形上下文,并使用UIGraphicsBeginImageContext使其成为当前上下文。
  • 借鉴上下文。
  • 从上下文中提取CGImageRef并将其转换为UIImage对象。
  • 在WKInterfaceGroup或WKInterfaceImage上显示图像。

码:

// 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是WKInterfaceImage属性。 这个对我有用。

我也可以在watchOS上使用UIBezierPath绘制如下:

// 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)

您可以在此处查看示例代码。

这是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)

这里的上下文不是CGContext,因此你有问题。 我不认为您可以直接在Apple Watch上使用Core Graphics。

这是示例项目,展示了如何在WatchKit 2.0上执行动态图形

https://github.com/vlm/ExampleWatchGraph

其中的要点是GraphPainter.swift文件,其中CoreGraphics用于绘制屏幕外缓冲区(如@ shu223建议的那样),然后在WKInterfaceImage中显示此缓冲区。

动画手表界面GIF

图形渲染在bezierPath的帮助下完成,并转换为图像以附加到Apple Watch

// Swift-3 Xcode-8.1

import UIKit类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
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM