ios 如何使用 UIBezierPath 创建 UIImage

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17408209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:10:44  来源:igfitidea点击:

How to create a UIImage with UIBezierPath

iosuiimageuibezierpath

提问by zedzhao

I wrote some code to create a UIImagewith UIBezierPathbut it didn't work.

我写了一些代码来创建一个UIImagewithUIBezierPath但它没有用。

Can someone help me find out what's wrong with my code?

有人可以帮我找出我的代码有什么问题吗?

-(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;
}

回答by Renderhp

try this category to UIBezierPath

试试这个类别到 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

回答by Leslie Godwin

Your usage would be:

您的用法是:

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

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

Category to create bezier path shapes:

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

@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

Category to take any path and render in UIImage from it:

使用任何路径并从中渲染 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

回答by Shrawan

You can create image with BeizerPath Swift-3 :-

您可以使用 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: 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
    }

}

enter image description here

在此处输入图片说明

Demo App

演示应用

Reference

参考

回答by coder1010

Try This

尝试这个

CAShapeLayer *maskLayer = [CAShapeLayer layer];

maskLayer.frame = imageview.frame;

maskLayer.path = [path CGPath];

imageview.layer.mask = maskLayer;

回答by zedzhao

I found what's wrong with my code.

我发现我的代码有什么问题。

I made a mistake on the code order. Simply move the UIGraphicsBeginImageContext(rect.size)to the appropriate position.

我在代码顺序上犯了一个错误。只需将 移动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;
}

回答by Leonif

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
    }
}

first view with Bezier

Bezier 的第一个视图

second - bezier transformed to image

第二个 - 贝塞尔转换为图像

enter image description here

在此处输入图片说明

回答by jrisberg

https://stackoverflow.com/a/17408397/3191351Translated Into Swift

https://stackoverflow.com/a/17408397/3191351翻译成 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
    }

}