Rounding UIImage and adding a border

前端 未结 9 1054
青春惊慌失措
青春惊慌失措 2020-12-09 18:19

so I want to show some pictures as annotations on the map. In order to do that I need to add the image property of the MKAnnotationView. I\'m using the regular images but I

相关标签:
9条回答
  • 2020-12-09 18:24

    I set masksToBounds, and It work.

    layer.masksToBounds = true
    
    0 讨论(0)
  • 2020-12-09 18:27

    For making an image rounded with border, you can do that from User Defined Runtime Attributes also, no need to write code for that.

    Please check the below image for setting that

    Also in your code, change

    imageView.layer.clipsToBounds = true
    

    to this,

    imageView.layer.masksToBounds = true
    
    0 讨论(0)
  • 2020-12-09 18:27

    you can create an IBDesignable class and set it to your Image. Then change properties in Storyboard with realtime changes

    @IBDesignable class CircularImageView: UIImageView {
    
    @IBInspectable var borderWidth : CGFloat {
        get { layer.borderWidth }
        set {
            layer.masksToBounds = true
            layer.borderWidth = newValue
            layer.cornerRadius = frame.size.width / 2
        }
    }
    
    @IBInspectable var borderColor: UIColor? {
        set {
            guard let uiColor = newValue else { return }
            layer.borderColor = uiColor.cgColor
        }
        get {
            guard let color = layer.borderColor else { return nil }
            return UIColor(cgColor: color)
        }
    }
    
    }
    
    0 讨论(0)
  • 2020-12-09 18:28

    Use this extension to UIImageView :

    func cropAsCircleWithBorder(borderColor : UIColor, strokeWidth: CGFloat)
    {
        var radius = min(self.bounds.width, self.bounds.height)
        var drawingRect : CGRect = self.bounds
        drawingRect.size.width = radius
        drawingRect.origin.x = (self.bounds.size.width - radius) / 2
        drawingRect.size.height = radius
        drawingRect.origin.y = (self.bounds.size.height - radius) / 2
    
        radius /= 2
    
        var path = UIBezierPath(roundedRect: CGRectInset(drawingRect, strokeWidth/2, strokeWidth/2), cornerRadius: radius)
        let border = CAShapeLayer()
        border.fillColor = UIColor.clearColor().CGColor
        border.path = path.CGPath
        border.strokeColor = borderColor.CGColor
        border.lineWidth = strokeWidth
        self.layer.addSublayer(border)
    
        path = UIBezierPath(roundedRect: drawingRect, cornerRadius: radius)
        let mask = CAShapeLayer()
        mask.path = path.CGPath
        self.layer.mask = mask
    }
    

    Usage :

            self.circleView.cropAsCircleWithBorder(UIColor.redColor(), strokeWidth: 20)
    

    Result :

    0 讨论(0)
  • 2020-12-09 18:31

    Leo Dabus's solution in Swift 3:

    extension UIImage {
        func roundedImageWithBorder(width: CGFloat, color: UIColor) -> UIImage? {
            let square = CGSize(width: min(size.width, size.height) + width * 2, height: min(size.width, size.height) + width * 2)
            let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square))
            imageView.contentMode = .center
            imageView.image = self
            imageView.layer.cornerRadius = square.width/2
            imageView.layer.masksToBounds = true
            imageView.layer.borderWidth = width
            imageView.layer.borderColor = color.cgColor
            UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
            guard let context = UIGraphicsGetCurrentContext() else { return nil }
            imageView.layer.render(in: context)
            let result = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return result
        }
    }
    
    0 讨论(0)
  • 2020-12-09 18:32

    If you would like to add a border to your image you need to make sure you add some extra room to it otherwise your border will be placed in top of your image. The solution is to add twice the width of your stroke to your image's width and height.

    extension UIImage {
        var isPortrait:  Bool    { size.height > size.width }
        var isLandscape: Bool    { size.width > size.height }
        var breadth:     CGFloat { min(size.width, size.height) }
        var breadthSize: CGSize  { .init(width: breadth, height: breadth) }
        var breadthRect: CGRect  { .init(origin: .zero, size: breadthSize) }
        func rounded(with color: UIColor, width: CGFloat) -> UIImage? {
            let bleed = breadthRect.insetBy(dx: -width, dy: -width)
            UIGraphicsBeginImageContextWithOptions(bleed.size, false, scale)
            defer { UIGraphicsEndImageContext() }
            guard let cgImage = cgImage?.cropping(to: CGRect(origin: CGPoint(
                x: isLandscape ? ((size.width-size.height)/2).rounded(.down) : 0,
                y: isPortrait  ? ((size.height-size.width)/2).rounded(.down) : 0),
                size: breadthSize))
            else { return nil }
            UIBezierPath(ovalIn: .init(origin: .zero, size: bleed.size)).addClip()
            var strokeRect =  breadthRect.insetBy(dx: -width/2, dy: -width/2)
            strokeRect.origin = .init(x: width/2, y: width/2)
            UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
                .draw(in: strokeRect.insetBy(dx: width/2, dy: width/2))
            color.set()
            let line: UIBezierPath = .init(ovalIn: strokeRect)
            line.lineWidth = width
            line.stroke()
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
    

    For iOS10+ We can use UIGraphicsImageRenderer.

    extension UIImage {
        var isPortrait:  Bool    { size.height > size.width }
        var isLandscape: Bool    { size.width > size.height }
        var breadth:     CGFloat { min(size.width, size.height) }
        var breadthSize: CGSize  { .init(width: breadth, height: breadth) }
        var breadthRect: CGRect  { .init(origin: .zero, size: breadthSize) }
        func rounded(with color: UIColor, width: CGFloat) -> UIImage? {
    
            guard let cgImage = cgImage?.cropping(to: .init(origin: .init(x: isLandscape ? ((size.width-size.height)/2).rounded(.down) : .zero, y: isPortrait ? ((size.height-size.width)/2).rounded(.down) : .zero), size: breadthSize)) else { return nil }
    
            let bleed = breadthRect.insetBy(dx: -width, dy: -width)
            let format = imageRendererFormat
            format.opaque = false
    
            return UIGraphicsImageRenderer(size: bleed.size, format: format).image { context in
                UIBezierPath(ovalIn: .init(origin: .zero, size: bleed.size)).addClip()
                var strokeRect =  breadthRect.insetBy(dx: -width/2, dy: -width/2)
                strokeRect.origin = .init(x: width/2, y: width/2)
                UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
                .draw(in: strokeRect.insetBy(dx: width/2, dy: width/2))
                context.cgContext.setStrokeColor(color.cgColor)
                let line: UIBezierPath = .init(ovalIn: strokeRect)
                line.lineWidth = width
                line.stroke()
            }
        }
    }
    

    Playground Testing:

    let profilePicture = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!
    let pp = profilePicture.rounded(with: .red, width: 10)
    
    0 讨论(0)
提交回复
热议问题