如何使用UIBezierPath创建UIImage

12

我编写了一些代码,用UIBezierPath创建一个UIImage,但是它没有起作用。

有人能帮我找出代码的问题吗?

-(UIImage*) drawTriangle{
    CGRect rect = CGRectMake(0.0, 0.0, 30.0, 30.0);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    UIBezierPath *bezier = [UIBezierPath bezierPathWithRect:rect];
    [bezier moveToPoint:CGPointMake(25, 5)];
    [bezier addLineToPoint:CGPointMake(5, 15)];
    [bezier addLineToPoint:CGPointMake(25, 25)];
    [bezier setLineWidth:3.0];
    [bezier setLineJoinStyle:kCGLineJoinBevel];
    [bezier stroke];
    CGContextAddPath(context, bezier.CGPath);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsPopContext();
    UIGraphicsEndImageContext();
    return image;
}
7个回答

14

尝试使用此类别到UIBezierPath

@interface UIBezierPath (Image)

/** Returns an image of the path drawn using a stroke */
-(UIImage*) strokeImageWithColor:(UIColor*)color;

@end

@implementation UIBezierPath (Image)

-(UIImage*) strokeImageWithColor:(UIColor*)color {
    // adjust bounds to account for extra space needed for lineWidth
    CGFloat width = self.bounds.size.width + self.lineWidth * 2;
    CGFloat height = self.bounds.size.height + self.lineWidth * 2;
    CGRect bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, width, height);

    // create a view to draw the path in
    UIView *view = [[UIView alloc] initWithFrame:bounds];

    // begin graphics context for drawing
    UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);

    // configure the view to render in the graphics context
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    // get reference to the graphics context
    CGContextRef context = UIGraphicsGetCurrentContext();

    // translate matrix so that path will be centered in bounds
    CGContextTranslateCTM(context, -(bounds.origin.x - self.lineWidth), -(bounds.origin.y - self.lineWidth));

    // set color
    [color set];

    // draw the stroke
    [self stroke];

    // get an image of the graphics context
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

    // end the context
    UIGraphicsEndImageContext();

    return viewImage;
}

@end

谢谢你,伙计。我没有尝试你的答案,因为我知道问题出在哪里。但还是谢谢你的回答。 - zedzhao
1
不需要创建视图,请查看我的帖子,其中包括要创建和呈现路径的两个类别。 - Leslie Godwin

8

您的使用方法如下:

UIBezierPath *path = [UIBezierPath trianglePathWithSize: CGSizeMake(50, 50)];
              path.lineWidth = 2;

UIImage *image = [path imageWithStrokeColor: [UIColor blueColor] 
                                  fillColor: [UIColor redColor]];

创建贝塞尔路径形状的类别:

@implementation UIBezierPath (Shapes)

+ (UIBezierPath *) trianglePathWithSize: (CGSize) size;
{
    UIBezierPath *result = [UIBezierPath bezierPath];
    result.lineJoinStyle = kCGLineJoinMiter;

    [result moveToPoint: CGPointMake(0, 0)];
    [result addLineToPoint: CGPointMake(size.width, size.height / 2)];
    [result addLineToPoint: CGPointMake(0, size.height)];
    [result closePath];

    return result;
}

@end

将任何路径的类别渲染为UIImage:

@implementation UIBezierPath (UIImage)

- (UIImage *) imageWithStrokeColor: (UIColor *) strokeColor fillColor: (UIColor *) 

fillColor;
{
    CGRect bounds = self.bounds;

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(bounds.size.width + self.lineWidth * 2, bounds.size.width + self.lineWidth * 2),
                                           false, [UIScreen mainScreen].scale);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // offset the draw to allow the line thickness to not get clipped
    CGContextTranslateCTM(context, self.lineWidth, self.lineWidth);

    if (!strokeColor)
    {
        strokeColor = fillColor;
    }
    else
    if (!fillColor)
    {
        fillColor = strokeColor;
    }

    [strokeColor setStroke];
    [fillColor setFill];

    [self fill];
    [self stroke];

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return result;
}

@end

5

您可以使用BeizerPath Swift-3创建图像:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var imageOutlet: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let path3 = createBeizePath()
        let image:UIImage = UIImage.shapeImageWithBezierPath(bezierPath: path3, fillColor: .red, strokeColor: .black)
        imageOutlet.image = image
}

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: bezierPath.bounds.width, height: bezierPath.bounds.height)
        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
    }

}

这里输入图片描述

演示应用

参考资料


那个可行,我只会改变这一部分 let size = CGSize(width: bezierPath.bounds.width, height: bezierPath.bounds.height) 这样路径就不会被扭曲。 - Tlacaelel Ramon Luis

4

试一试

CAShapeLayer *maskLayer = [CAShapeLayer layer];

maskLayer.frame = imageview.frame;

maskLayer.path = [path CGPath];

imageview.layer.mask = maskLayer;

let newLayer = CAShapeLayer() newLayer.frame = customImage.frame newLayer.path = path.cgPath customImage.layer.mask = newLayer - Prince Kumar

3
extension UIBezierPath {
    func shapeImage(view: UIView) -> UIImage! {
    
    // begin graphics context for drawing
    UIGraphicsBeginImageContextWithOptions(view.frame.size, false, UIScreen.main.scale)
    
    // configure the view to render in the graphics context
    //view.layer.render(in: UIGraphicsGetCurrentContext()!)
    
    // get reference to the graphics context
    let context = UIGraphicsGetCurrentContext()
    
    // translate matrix so that path will be centered in bounds
    context?.translateBy(x: -(bounds.origin.x - self.lineWidth), y: -(bounds.origin.y - self.lineWidth))
    // set color
    UIColor.black.setStroke()
    
    // draw the stroke
    stroke()
    
    // get an image of the graphics context
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    
    // end the context
    UIGraphicsEndImageContext()
    
    return image
    }
}

2

https://dev59.com/rmQm5IYBdhLWcg3wswtv#17408397 翻译成 Swift

import UIKit

extension UIBezierPath {

    /** Returns an image of the path drawn using a stroke */
    func strokeImageWithColor(var strokeColor: UIColor?,var fillColor: UIColor?) -> UIImage {

        // get your bounds
        let bounds: CGRect = self.bounds

        UIGraphicsBeginImageContextWithOptions(CGSizeMake(bounds.size.width + self.lineWidth * 2, bounds.size.width + self.lineWidth * 2), false, UIScreen.mainScreen().scale)

        // get reference to the graphics context
        let reference: CGContextRef = UIGraphicsGetCurrentContext()!

        // translate matrix so that path will be centered in bounds
        CGContextTranslateCTM(reference, self.lineWidth, self.lineWidth)

        if strokeColor == nil {
            strokeColor = fillColor!;
        }
        else if fillColor == nil {
            fillColor = strokeColor!;
        }

        // set the color
        fillColor?.setFill()
        strokeColor?.setStroke()

        // draw the path
        fill()
        stroke()


        // grab an image of the context
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()

        return image
    }

}

2

我找到了代码的问题所在。

我的代码顺序有误。只需将UIGraphicsBeginImageContext(rect.size)移动到适当的位置即可。

-(UIImage*) drawTriangle{
    CGRect rect = CGRectMake(0.0, 0.0, 30.0, 30.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    UIGraphicsBeginImageContext(rect.size); //now it's here.
    UIBezierPath *bezier = [UIBezierPath bezierPathWithRect:rect];
    [bezier moveToPoint:CGPointMake(25, 5)];
    [bezier addLineToPoint:CGPointMake(5, 15)];
    [bezier addLineToPoint:CGPointMake(25, 25)];
    [bezier setLineWidth:3.0];
    [bezier setLineJoinStyle:kCGLineJoinBevel];
    [bezier stroke];
    CGContextAddPath(context, bezier.CGPath);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsPopContext();
    UIGraphicsEndImageContext();
    return image;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接