问题
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 want them to be rounded and with a border. So I found a way to round UIImage and I found the way to add a border to UIImage, but border doesn't seem to add (I'm not actually having the image on the screen, maybe that is the problem?).
I used this answer https://stackoverflow.com/a/29047372/4665643 with a slight modification for border. Namely:
imageView.layer.borderWidth = 1.5
imageView.layer.borderColor = UIColor.whiteColor().CGColor
imageView.clipsToBounds = true
But my image on the map doesn't have any border. Any suggestions ?
回答1:
imageView.layer.masksToBounds = true
imageView.layer.borderWidth = 1.5
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.cornerRadius = imageView.bounds.width / 2
Try this.
回答2:
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    { return size.height > size.width }
    var isLandscape: Bool    { return size.width > size.height }
    var breadth:     CGFloat { return min(size.width, size.height) }
    var breadthSize: CGSize  { return CGSize(width: breadth, height: breadth) }
    var breadthRect: CGRect  { return CGRect(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: CGRect(origin: .zero, size: bleed.size)).addClip()
        var strokeRect =  breadthRect.insetBy(dx: -width/2, dy: -width/2)
        strokeRect.origin = CGPoint(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(ovalIn: strokeRect)
        line.lineWidth = width
        line.stroke()
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}
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)
    回答3:
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
    回答4:
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 :
回答5:
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
    }
}
    回答6:
simple one line code its works for me
self.profileImage.layer.cornerRadius = self.profileImage.frame.size.width / 2
    回答7:
I set masksToBounds, and It work.
layer.masksToBounds = true
    回答8:
Just fixed it. Apparently everything was working perfectly but I wasn't seeing the border. The original image is about 300x300 pixels and with 1.5 pixel border I was cropping it to fit 40x40 frame so the border was barely noticeable. Changing border width to a bigger number made it visible.
来源:https://stackoverflow.com/questions/34984966/rounding-uiimage-and-adding-a-border