とあるコーディングにおいて、色を滑らかに変化させる必要があったのでメモメモ。
RGB ではなく HSV で考える
何らかのプログラミング言語から虹色のグラデーションを作る必要がある場合、RGB の色空間で色調整を行うのは大変ですが、HSV の色空間で考えると簡単に表現することができます。

HSV はそれぞれ下記のような情報を表しており、
- 色相 (Hue): 0~360
- 彩度 (Saturation・Chroma): 0~1
- 明度 (Value・Brightness): 0~1
このうち、色相 (Hue) の値を 0~360 の間で変化させてやることでレインボーカラーを表現することができます。
プログラムのサンプル

例えば、Android では、android.graphics.Color.HSVToColor()
という関数を使用すると、HSV 色空間における値を、描画に使用するカラーデータに変換することができます。
下記の ColorGenerator
クラスの nextColor()
メソッドを連続して呼び出すと、徐々に変わっていく色をひとつずつ取り出すことができます。
やっていることは、メソッドの呼び出しごとに、色相 (Hue) の値を少しずつ変化させているだけです。
色相 (Hue) が、何度の nextColor()
呼び出しで一周するかは、コンストラクタの steps
パラメータで指定できるようにしています。
class ColorGenerator(val steps: Int, initialHue: Float = 0.0F) {
private val hueStep: Float = 360F / steps
private var currentHue = initialHue
fun nextColor(): Int {
val hsv = floatArrayOf(currentHue, 1.0F, 1.0F)
val color: Int = Color.HSVToColor(255, hsv)
currentHue = (currentHue + hueStep) % 360F
return color
}
}
次のコードは、このクラスを使って、虹色のグラデーション(細い矩形の連続)を描画するコードの抜粋です。 ここでは、色を 30 段階に分けて描画しています。
val colorGen = ColorGenerator(30)
override fun onDraw(canvas: Canvas){
var left = 0F
val paint = Paint()
for (i in 0 until colorGen.steps) {
paint.color = colorGen.nextColor()
c.drawRect(left, 0F, left + 10, 100F, paint)
left += 10
}
}