【问题标题】:How to create a UIImage with UIBezierPath如何使用 UIBezierPath 创建 UIImage
【发布时间】:2013-07-01 15:29:29
【问题描述】:

我编写了一些代码来使用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;
}

【问题讨论】:

    标签: ios uiimage uibezierpath


    【解决方案1】:

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

    【讨论】:

    • 谢谢,我没有尝试您的答案,因为我知道问题出在哪里。但仍然感谢您的回答
    • 无需创建视图,查看我的帖子,其中包含 2 个类别来创建和渲染路径。
    【解决方案2】:

    你的用法是:

    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
    

    【讨论】:

      【解决方案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: 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
          }
      
      }
      

      Demo App

      Reference

      【讨论】:

      • 那行得通,我只需要改变这部分 let size = CGSize(width: bezierPath.bounds.width, height: bezierPath.bounds.height) 这样路径就不会变形
      【解决方案4】:

      试试这个

      CAShapeLayer *maskLayer = [CAShapeLayer layer];
      
      maskLayer.frame = imageview.frame;
      
      maskLayer.path = [path CGPath];
      
      imageview.layer.mask = maskLayer;
      

      【讨论】:

      • 让 newLayer = CAShapeLayer() newLayer.frame = customImage.frame newLayer.path = path.cgPath customImage.layer.mask = newLayer --- swift 5.0 版本
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:
          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
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多