Skip to content

Instantly share code, notes, and snippets.

@bteapot
Last active July 27, 2020 15:02
Show Gist options
  • Save bteapot/8d4896f30dd7a2d50f169f50f23b68bc to your computer and use it in GitHub Desktop.
Save bteapot/8d4896f30dd7a2d50f169f50f23b68bc to your computer and use it in GitHub Desktop.
UIImage extension for generating two-letter avatars with reproducible color.
import Foundation
import UIKit
extension UIFont {
func with(traits: UIFontDescriptor.SymbolicTraits) -> UIFont {
if let fontDescriptor = self.fontDescriptor.withSymbolicTraits(traits) {
return UIFont(descriptor: fontDescriptor, size: 0)
} else {
return self
}
}
func with(weight: UIFont.Weight) -> UIFont {
let fontDescriptor = self.fontDescriptor.addingAttributes([
.traits: [
UIFontDescriptor.TraitKey.weight: weight,
],
])
return UIFont(descriptor: fontDescriptor, size: 0)
}
}
import Foundation
import UIKit
extension UIImage {
class func avatar(
id: Int = 0,
text: String?,
size: CGSize,
saturation: CGFloat = 0.40,
brightness: CGFloat = 0.80,
font: UIFont? = nil,
corners: CGFloat = 0,
placeholder: UIImage?
) -> UIImage? {
// есть текст?
guard let text = text, text.isEmpty == false else {
return placeholder
}
// вычислим инициалы
let words: [String] = text.components(separatedBy: CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters))
let first: [String] = words.compactMap({ $0.first }).map(String.init)
let initials = { () -> String in
switch first.count {
case 2...: return first[0] + first[1]
case 1: return String(first[0].prefix(2))
default: return ""
}
}().uppercased()
// пусто?
guard initials.isEmpty == false else {
return placeholder
}
// хэш
let hash: UInt = UInt(bitPattern: (String(id) + initials).hashValue)
// оттенок
let hue = CGFloat(hash % 360) / 360
// цвета
let backgroundColor =
UIColor(
hue: hue,
saturation: saturation,
brightness: brightness,
alpha: 1
)
let textColor =
UIColor(
hue: 0,
saturation: 0,
brightness: brightness > 0.8 ? 0.2 : 1.0,
alpha: 1
)
// шрифт
let font: UIFont = font ?? UIFont.systemFont(ofSize: floor(size.height / 2), weight: .regular).with(traits: .traitCondensed)
// нарисуем и отдадим картинку
return UIGraphicsImageRenderer(size: size).image { context in
// фон
backgroundColor.setFill()
UIBezierPath(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: corners).fill()
// текст
let attributedText = NSAttributedString(string: initials, attributes: [
.font: font,
.foregroundColor: textColor,
])
let options: NSStringDrawingOptions = [.usesLineFragmentOrigin]
let textSize = attributedText.boundingRect(with: .zero, options: options, context: nil).size
let textRect = CGRect(x: (size.width - textSize.width) / 2, y: (size.height - textSize.height) / 2, width: textSize.width, height: textSize.height)
attributedText.draw(with: textRect, options: options, context: nil)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment