Swift 3:从UIBezierPath创建UIImage

Jea*_*ean 2 uiimageview uiimage ios uibezierpath swift

我有一个UIBezierPath,最终我需要一个UIImageView。现在,我正在尝试先创建一个UIImage,然后再UIImageView从中创建一个。

我工作很快,而且我也看过类似的问题,答案要么不起作用,要么产生形状而不是曲线。我的贝塞尔曲线代表草图,而不是实际形状。我不想关闭贝塞尔曲线,这就是这样UIImage.shapeImageWithBezierPath()做的。最后一种解决方案是唯一实际封装完整曲线的解决方案。所有其他解决方案要么产生碎片,要么根本不显示。

最终目标是CollectionView使用这些曲线作为列表中的项目创建一个,这意味着我最终必须UIBeziers输入CollectionViewCells

提前致谢。

Rob*_*Rob 6

如果需要UIImage(可以与一起使用UIImageView),则可以使用UIGraphicsImageRenderer

private func image(with path: UIBezierPath, size: CGSize) -> UIImage {
    return UIGraphicsImageRenderer(size: size).image { _ in
        UIColor.blue.setStroke()
        path.lineWidth = 2
        path.stroke()
    }
}
Run Code Online (Sandbox Code Playgroud)

这是iOS 10中引入的。如果需要支持早期的iOS版本,则可以使用UIGraphicsGetImageFromCurrentImageContext

private func image(with path: UIBezierPath, size: CGSize) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    UIColor.blue.setStroke()
    path.lineWidth = 2
    path.stroke()
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}
Run Code Online (Sandbox Code Playgroud)

另外,UIImage如果需要,您可以绕过the ,而只需使用以下方法定义一个UIView子类CAShapeLayer

@IBDesignable
class ShapeView: UIView {

    @IBInspectable var lineWidth:   CGFloat = 1   { didSet { shapeLayer.lineWidth   = lineWidth } }
    @IBInspectable var strokeColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 1, alpha: 1)  { didSet { shapeLayer.strokeColor = strokeColor.cgColor } }
    @IBInspectable var fillColor:   UIColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0)  { didSet { shapeLayer.fillColor   = fillColor.cgColor } }

    var path:  UIBezierPath? { didSet { shapeLayer.path = path?.cgPath } }

    private let shapeLayer = CAShapeLayer()

    override init(frame: CGRect) {
        super.init(frame: frame)

        configure()
    }

    convenience init() {
        self.init(frame: .zero)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        configure()
    }

    /// Add and configure the view.
    ///
    /// Add and configure shape.

    private func configure() {
        layer.addSublayer(shapeLayer)

        shapeLayer.strokeColor = self.strokeColor.cgColor
        shapeLayer.fillColor   = self.fillColor.cgColor
        shapeLayer.lineWidth   = self.lineWidth
    }

    // just add some path so if you used this in IB, you'll see something

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        shapeLayer.path = UIBezierPath(ovalIn: bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)).cgPath
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这是可行的,但我意识到自己做错了。Bezier路径是使用CGPoints手动计算的,而从CGFrames到UIImages的转换是元凶。所以我有一些事情要解决 (2认同)