【问题标题】:Creating an SKSpriteNode from the SF Symbols font, in a different color从 SF Symbols 字体创建一个不同颜色的 SKSpriteNode
【发布时间】:2020-05-10 04:33:00
【问题描述】:

我正在尝试使用 SF Symbols 字体中的图像创建一个 SKSpriteNode,虽然我可以做到,但我似乎无法将其设为黑色以外的任何颜色。

这是我的代码:

let image = UIImage.init(systemName: "gear")
let colored = image!.withTintColor(.red)
let texture = SKTexture.init(image: colored)
let sprite = SKSpriteNode.init(texture: texture, size: CGSize.init(width: 32, height: 32))

不幸的是,生成的精灵总是以黑色(而不是红色)出现。

我做错了什么?

【问题讨论】:

  • 只是猜测(没有尝试过),但可能是withTintColor(.red, renderingMode: .alwaysOriginal)?
  • 或者.alwaysTemplate,关键是它为制作纹理的上下文选择的任何模式,试试另一个......
  • @bg2b 我试过.alwaysOriginal 还是一样,我再试试看是否有什么不同。
  • …。齿轮是黑色的吗?
  • 这个答案中的extension 帮助了我stackoverflow.com/a/52921562/285190

标签: swift sprite-kit sf-symbols


【解决方案1】:

我认为问题在于 UIImage 是矢量图形,只有 UIImageViews 才能正确处理它们。 也许我们可以将其强制为位图图像以使其正常工作。

这里有一些你可以尝试的实验代码:

let image = UIImage(systemName: "gear").withTintColor(.red)

let data = image.pngData()
let newImage = UIImage(data:data) 
let texture = SKTexture(image: newImage)
let sprite = SKSpriteNode(texture: texture,size: CGSize(width: 32, height: 32))

【讨论】:

  • 这会产生一个完全白色的 32x32 框。当我在调试器中查看我的代码时,colored 图像是红色的(正确的)但是当将它放入纹理时它又变黑了。
  • 好的,我有时间研究一下。符号图像呈现给定的色调颜色,因为它是矢量图形。很确定我已经看到只有 UIImageView 可以正确处理矢量图形。更新其他内容
【解决方案2】:

你必须在精灵上设置colorBlendFactor

func makeSprite(symbolName: String) -> SKSpriteNode {
    let image = Image(systemName: symbolName)

    // Thanks Oskar!
    // https://stackoverflow.com/a/69315037/1610473
    // See my adapted version of his code further down; I
    // think you won't need it if you're on iOS, meaning
    // using UIImage, but that's all black magic to me.
    let renderedByOskar = image.renderAsImage()!

    let texture = SKTexture(image: renderedByOskar)
    let sprite = SKSpriteNode(texture: texture)

    sprite.color = .green
    sprite.colorBlendFactor = 1 // <-- This

    return sprite
}

一个绿色的符号,多亏了黑魔法:

非常感谢 Oskar 提供的 rendering extensions 使我能够在 macOS 上执行此操作,也就是说,没有 UIImage

class NoInsetHostingView<V>: NSHostingView<V> where V: View {
    override var safeAreaInsets: NSEdgeInsets {
        return .init()
    }
}

extension Image {
    func renderAsImage() -> NSImage? {
        let view = NoInsetHostingView(rootView: self)
        view.setFrameSize(view.fittingSize)
        return view.bitmapImage()
    }
}

public extension NSView {
    func bitmapImage() -> NSImage? {
        guard let rep = bitmapImageRepForCachingDisplay(in: bounds) else {
            return nil
        }

        cacheDisplay(in: bounds, to: rep)

        guard let cgImage = rep.cgImage else {
            return nil
        }

        return NSImage(cgImage: cgImage, size: bounds.size)
    }
}

【讨论】:

    猜你喜欢
    • 2021-11-17
    • 2021-10-16
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    相关资源
    最近更新 更多