NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

【SwiftUI】renderingModeでImageに色をつける

SwiftUIではforegroundColorを使用する事で色を変更する事ができますが、Assetsに用意したImageはrenderingModeでtemplateを指定しないとforegroundColorで指定した色を反映させる事ができません。 今回はrenderingModeのtemplateで色んなファイル形式の違うImageにて色を変更させてみました。

renderingMode

renderingとは元のデータを整形して出力することで、SwiftUIではAssetsで用意したImageはrenderingModeでtemplate を定義することで指定した色を反映させる事ができます。
以下モードとそれぞれの説明です。

renderingMode 内容
original ビットマップ画像のピクセルをそのままレンダリングするモード。
template すべての不透明なピクセルを前景色としてレンダリングするモード。

使用例

とりあえずpng形式のImageを用意して試しました。

original

Image("pngImage")
    .renderingMode(.original)
    .foregroundColor(Color.red)
    .background(Color.blue)

背景色は反映さえれていますが図の色はそのままレンダリングされています。

template

Image("pngImage")
    .renderingMode(.template)
    .foregroundColor(Color.red)
    .background(Color.blue)

図の色も反映されています。

その他ファイル形式

予想ではpng、svgのみうまくいくと思っていましたがpdfでも普通に反映されていました!
(確かにpdfにもラスタやベクタがあるのでできるのか)
jpegは予想通り背景も全てベタ塗りになりました!

Sample​(作ってみた)

せっかくなので色んな色のImageを散りばめてぼかして背景っぽい画像を作ってみました。

class RandomColorGenerator: ObservableObject {
    private var redAmount:Double = 0.0
    private var greenAmount: Double = 0.0
    private var blueAmount: Double = 0.0
    @Published var randomColor: Color = Color(red: 1.0, green: 1.0, blue: 1.0)
    
    func randomColorGenerator() {
        redAmount = Double.random(in: 0.0000000...1)
        greenAmount = Double.random(in: 0.0000000...1)
        blueAmount = Double.random(in: 0.0000000...1)
        randomColor = Color (red: redAmount, green: greenAmount, blue: blueAmount, opacity: 0.4)
    }
}

​ ​Imageに対してランダムな色付けをするViewのコンポーネントを作成。 ​

struct ImageView: View {
    @ObservedObject private var colorGenerator = RandomColorGenerator()
    var body: some View {
        Image("pngImage")
            .renderingMode(.template)
            .resizable()
            .frame(width: 50, height: 50)
            .foregroundColor(colorGenerator.randomColor)
            .onAppear() {
                colorGenerator.randomColorGenerator()
            }
    }
}

先ほどのViewコンポーネントをを50枚繰り返し処理で重ねていく。 ​

struct ImageDisplayView: View {
    private let halfScreenWidthSize = UIScreen.main.bounds.width / 2
    private let halfScreenHeigthSize = UIScreen.main.bounds.height / 2
    var body: some View {
        ZStack {
            ForEach (0..<50) { item in
                ImageView()
                    .offset(x: CGFloat.random(in: -halfScreenWidthSize...halfScreenWidthSize), y: CGFloat.random(in: -halfScreenHeigthSize...halfScreenHeigthSize))
            }
        }
    }
}

完成イメージ
​ 全く実用的ではないですができました!笑

おまけ(UIImage)

UIImageで使用したい場合は以下のようにwithRenderingModeを使用する事でtintColorで指定した色を反映させる事ができます。 ​

let uiImage = UIImage(named: "imageName")?.withRenderingMode(.alwaysTemplate)

参考記事

developer.apple.com

developer.apple.com

developer.apple.com