🦋
SwiftUI: GraphicsContextで任意の色のTextやImageをDrawする
SwiftUIのCanvas
やImage
にはGraphicsContext
で動的に描画するものを制御できるAPIがあります。
例
let size = CGSize(width: 100, height: 100)
var body: some View {
Canvas { context, size in
context.draw(Text("Hello World!"), in: CGRect(origin: .zero, size: size))
context.draw(Image(systemName: "globe"), at: .zero)
}
Image(size: size) { context in
context.draw(Text("Hello World!"), in: CGRect(origin: .zero, size: size))
context.draw(Image(systemName: "globe"), at: .zero)
}
}
問題
このGraphicsContext
で描画するText
やImage
の色を指定したい場合にforegroundStyle()
を用いると、No exact matches in call to instance method 'draw'
というコンパイルエラーになります。これはforegroundStyle()
モディファイアがText
やImage
をView
に変換してしまうためです。
Canvas { context, size in
let text = Text("Hello World!").foregroundStyle(Color.blue)
context.draw(text, in: CGRect(origin: .zero, size: size)) // compile error
let image = Image(systemName: "globe").foregroundStyle(Color.blue)
context.draw(image, at: .zero) // compile error
}
対策
GraphicsContext.resolve()
を使い、GraphicsContext.ResolvedText
やGraphicsContext.ResolvedImage
としてshading
に色を指定します。
Canvas { context, size in
var text = context.resolve(Text("Hello World!"))
text.shading = .color(.blue)
context.draw(text, in: CGRect(origin: .zero, size: size))
var image = context.resolve(Image(systemName: "globe"))
image.shading = .color(.blue)
context.draw(image, at: .zero)
}
shading
にはcolor
以外にもlinearGradient
やradialGradient
などのグラデーションもあるので、色々試してみると良いかもしれません。
Discussion