Округление UIImage и добавление границы

Поэтому я хочу показать некоторые картинки в виде аннотаций на карте. Для этого мне нужно добавить свойство изображения MKAnnotationView. Я использую обычные изображения, но я хочу, чтобы они были округлены и с рамкой. Таким образом, я нашел способ округлить UIImage и нашел способ добавить границу в UIImage, но граница, кажется, не добавляет (у меня фактически нет изображения на экране, может быть, в этом проблема?).

Я использовал этот ответ /questions/24891997/razrezhte-uiimage-v-krug/24892006#24892006 с небольшим изменением границы. А именно:

imageView.layer.borderWidth = 1.5
imageView.layer.borderColor = UIColor.whiteColor().CGColor
imageView.clipsToBounds = true

Но мое изображение на карте не имеет границ. Какие-либо предложения?

8 ответов

imageView.layer.masksToBounds = true
imageView.layer.borderWidth = 1.5
imageView.layer.borderColor = .white.cgColor
imageView.layer.cornerRadius = imageView.bounds.width / 2

Попробуй это.

Если вы хотите добавить рамку к вашему изображению, вам нужно убедиться, что вы добавили к нему дополнительное пространство, иначе ваша рамка будет помещена поверх вашего изображения. Решение состоит в том, чтобы добавить удвоенную ширину штриха к ширине и высоте вашего изображения.

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

Тестирование игровой площадки:

let profilePicture = UIImage(data: try! Data(contentsOf: URL(string:"https://stackru.com/images/ef9dfaef8c3bec7e67a69584eb37fe5a3e115132.jpg")!))!
let pp = profilePicture.rounded(with: .red, width: 10)

РешениеЛео Дабуса в 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
    }
}

Используйте это расширение для 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
}

Использование:

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

Результат:

Результат

Чтобы сделать изображение округленным с рамкой, вы также можете сделать это из пользовательских атрибутов времени выполнения, для этого не нужно писать код.

Пожалуйста, проверьте изображение ниже для установки этого

введите описание изображения здесь

Также в вашем коде измените

imageView.layer.clipsToBounds = true

к этому,

imageView.layer.masksToBounds = true

Добавлена ​​поддержка изображений

Я устанавливаю masksToBounds, и это работает.

layer.masksToBounds = true

Вы можете создать класс IBDesignable и установить для него свой Image. Затем измените свойства в Storyboard с изменениями в реальном времени

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

}

Простой однострочный код работает для меня

self.profileImage.layer.cornerRadius = self.profileImage.frame.size.width / 2

Просто исправил это. Видимо все работало отлично, но я не видел границы. Исходное изображение размером около 300x300 пикселей и с рамкой 1,5 пикселя, я обрезал его до размера кадра 40x40, чтобы граница была едва заметной. Изменение ширины границы на большее число сделало ее видимой.

Другие вопросы по тегам