将苹果表情符号(字符串)转换为UIImage

60

我需要所有的苹果表情符号。
我可以从网站getemoji复制所有表情符号并将它们放入字符串中,但是在我的应用程序中,我需要按正确的顺序以图像的形式呈现这些表情符号。

有没有一种好方法可以将我复制到字符串中的表情符号转换为UIImage
或者获得所有苹果表情符号的更好解决方案?

9个回答

106

已更新至Swift 4.1

将此扩展添加到您的项目中。

import UIKit

extension String {
    func image() -> UIImage? {
        let size = CGSize(width: 40, height: 40)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.white.set()
        let rect = CGRect(origin: .zero, size: size)
        UIRectFill(CGRect(origin: .zero, size: size))
        (self as AnyObject).draw(in: rect, withAttributes: [.font: UIFont.systemFont(ofSize: 40)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

上面的代码将当前的String绘制到白色背景的 Image Context 中,最后将其转换为UIImage

现在您可以编写:

输入图像描述

示例

给定一个表示表情符号 Unicode 值范围的列表

let ranges = [0x1F601...0x1F64F, 0x2702...0x27B0]

你可以将它转换成一系列图片。

let images = ranges
    .flatMap { $0 }
    .compactMap { Unicode.Scalar($0) }
    .map(Character.init)
    .compactMap { String($0).image() }

结果:

图片描述

我不能保证范围列表是完整的,你需要自己搜索它。


@Danny182:请查看我的更新。下次如果您有更多的请求,请创建一个新的问题。 - Luca Angeletti
由于范围会混合(新的表情符具有奇怪的Unicode),所以使用范围将无法工作。我已经将所有表情符存储在一个数组[String] @appzYourLife中。 - DanielZanchi
1
但这不是基于矢量的图形了。 - Oleksii Nezhyborets
将绘图原点设置为CGPoint(x:2,y:-1),字体大小设置为34,并且表情符号也将居中并适合于图像中。 - Daniel
1
@Jonauz:你试过使用UIColor.clear.set()而不是UIColor.white.set()吗? - Karol Kulesza
显示剩余3条评论

27

以下是更新后的答案:

Swift 5

import UIKit
extension String {
    func textToImage() -> UIImage? {
        let nsString = (self as NSString)
        let font = UIFont.systemFont(ofSize: 1024) // you can change your font size here
        let stringAttributes = [NSAttributedString.Key.font: font]
        let imageSize = nsString.size(withAttributes: stringAttributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) //  begin image context
        UIColor.clear.set() // clear background
        UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
        nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
        UIGraphicsEndImageContext() //  end image context

        return image ?? UIImage()
    }
}

Swift 3.2

import UIKit
extension String {
    func textToImage() -> UIImage? {
        let nsString = (self as NSString)
        let font = UIFont.systemFont(ofSize: 1024) // you can change your font size here
        let stringAttributes = [NSFontAttributeName: font]
        let imageSize = nsString.size(attributes: stringAttributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) //  begin image context
        UIColor.clear.set() // clear background
        UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
        nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
        let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
        UIGraphicsEndImageContext() //  end image context

        return image ?? UIImage()
    }
}

为什么要返回一个可选项? 扩展字符串 { func textToImage() -> UIImage? { 如果您有一个默认的空图像 返回图像??UIImage() - Muvimotv
有Objective-C版本吗? - undefined

12

对于Swift 4也是同样的情况:

extension String {
    func emojiToImage() -> UIImage? {
        let size = CGSize(width: 30, height: 35)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.white.set()
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(rect)
        (self as NSString).draw(in: rect, withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 30)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

9

更新@Luca Angeletti的答案,适用于Swift 3.0.1版本

extension String {

    func image() -> UIImage? {
        let size = CGSize(width: 30, height: 35)
        UIGraphicsBeginImageContextWithOptions(size, false, 0);
        UIColor.white.set()
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(CGRect(origin: CGPoint(), size: size))
        (self as NSString).draw(in: rect, withAttributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 30)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

}

7

Swift 4.2

我非常喜欢 @Luca Angeletti 的解决方案。我和 @jonauz 有同样的问题,关于透明背景。所以通过这个小修改,你可以得到相同的效果,但是背景颜色为清晰的。

我没有足够的声望在评论中回答。

import UIKit

extension String {
    func emojiToImage() -> UIImage? {
        let size = CGSize(width: 30, height: 35)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.clear.set()
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(CGRect(origin: CGPoint(), size: size))
        (self as NSString).draw(in: rect, withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 30)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

7

Swift 5:(带有可选的字体大小、图像尺寸和背景颜色)

使用方法如下:

let image      = "".image()
let imageLarge = "".image(fontSize:100)
let imageBlack = "".image(fontSize:100, bgColor:.black)
let imageLong  = "".image(fontSize:100, imageSize:CGSize(width:500,height:100))


import UIKit

extension String
{
    func image(fontSize:CGFloat = 40, bgColor:UIColor = UIColor.clear, imageSize:CGSize? = nil) -> UIImage?
    {
        let font = UIFont.systemFont(ofSize: fontSize)
        let attributes = [NSAttributedString.Key.font: font]
        let imageSize = imageSize ?? self.size(withAttributes: attributes)

        UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
        bgColor.set()
        let rect = CGRect(origin: .zero, size: imageSize)
        UIRectFill(rect)
        self.draw(in: rect, withAttributes: [.font: font])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

1
在你的回答中,表情符号没有居中。 - Vitalik Kizlov
@VitalikKizlov 参考我的答案,并且请随意(您或此答案的作者Jolly Jinx)根据我的答案编辑这个Swift5答案。使用draw(at:withAttributes:)代替draw(in:withAttributes:) - om-ha

3

使用 UIGraphicsImageRenderer 更新了 @Luca Angeletti 的答案的版本:

extension String {
    func image() -> UIImage? {
        let size = CGSize(width: 100, height: 100)
        let rect = CGRect(origin: CGPoint(), size: size)
        return UIGraphicsImageRenderer(size: size).image { (context) in
            (self as NSString).draw(in: rect, withAttributes: [.font : UIFont.systemFont(ofSize: 100)])
        }
    }
}

1

这个变化基于@Luca's的答案,但允许您可选地自定义字体的点大小,应该会产生一个居中的图像,并且不会使背景颜色变为白色。

extension String {
    func image(pointSize: CGFloat = UIFont.systemFontSize) -> UIImage? {
        let nsString = self as NSString
        let font = UIFont.systemFont(ofSize: pointSize)

        let size = nsString.size(withAttributes: [.font: font])
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        let rect = CGRect(origin: .zero, size: size)
        nsString.draw(in: rect, withAttributes: [.font: font])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

1
其实比建议的答案要简单得多。
extension String {
    func image(pointSize: CGFloat, backgroundColor: UIColor = .clear) -> UIImage {
        let font = UIFont.systemFont(ofSize: pointSize)
        let emojiSize = self.size(withAttributes: [.font: font])

        return UIGraphicsImageRenderer(size: emojiSize).image { context in
            backgroundColor.setFill()
            context.fill(CGRect(origin: .zero, size: emojiSize))
            self.draw(at: .zero, withAttributes: [.font: font])
        }
    }
}

Screenshot from playground


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接