🎨

JavaScript Tips - 文字列をランダムかつ固定な色(hsl)に変換する方法

2021/01/15に公開

はじめに

今回は, titlescreen_name といった変数に設定するような文字列を, ランダムかつ固定な色に変換する Tips を紹介したいと思います. 固定というのは, 一度決まった色は画面をリロードしても変わらないという意味です.

現場でもよく使ってる便利なテクニックなのでよかったら参考にしてください.

実例と主な用途

いまいち何が便利かうまく説明できていない気がするので, 実際に使っている例の画像を貼っておきます.

社内で作ってるタスク管理システムなんですが, リストの上に色の付いている帯があるのがわかると思います.

これは個別に指定しているわけではなく, opentodo といった文字列から一意の数値に変換しそれを色に変えることで極力重複しない色を自動で割り当てるようにしています.

他にも, 以下のような場面などで活用できると思います.

  • デフォルトアイコンの背景色をカラフルにしたい
  • ユーザーアイコンの縁に色をつけたい
  • プロジェクトのプライマリーカラーに, 自動でかつ重複しない色を設定したい
  • 投稿の背景画像をうっすらユニークな色にしたい

サンプルプログラム

まずはサンプルです.
フォームに文字列を入力すると背景の色が変わります.

また, 同じ文字列は必ず同じ色になるようになっているのがわかるかと思います.

https://runstant.com/phi/projects/e0868e41

コード

HTML

index.html
<body>
  <h1>${title}</h1>

  <form>
    <input id='$input' type='text' value='zenn.dev' placeholder='何か入力してね!' />
  </form>
  
  <script>${script}</script>
</body>

JavaScript

main.js
window.onload = function() {
  // 入力されるたびに実行されるイベントを登録
  $input.oninput = () => {
    // 何も入力されてなければ抜ける
    if (!$input.value) return ;
    
    // 入力した文字列を数値に変換
    var n = stringToNumber($input.value);
    // hsl 用に 0 ~ 360 に収める
    var colorAngle = (n*n) % 360;
    
    // hsl の色相(Hue)部分に文字列から変換した数値を割り当てる
    document.body.style.backgroundColor = `hsl(${colorAngle}, 80%, 64%)`;
  };
  
  // 全選択
  $input.onfocus = () => { $input.select() };
  // 一回実行しておく
  $input.oninput();
};

// 文字列を適当な数値に変換する
var stringToNumber = (str) => {
  // 文字列 -> 配列 -> 文字コードの配列 -> 全部足す
  return Array.from(str).map(ch => ch.charCodeAt(0)).reduce((a, b) => a+b);
};

解説

文字列を数値に変換しよう

この辺の計算ロジックは色々と考えられますが文字列から一意の数値に変換できれば良いので以下のような処理になっています.

// 文字列を適当な数値に変換する
var stringToNumber = (str) => {
  // 文字列 -> 配列 -> 文字コードの配列 -> 全部足す
  return Array.from(str).map(ch => ch.charCodeAt(0)).reduce((a, b) => a+b);
};

ワンライナーで書いちゃってるのでわかりにくいかもですが, 流れとしては

  1. Array.from() で文字列を分解して配列にする
  2. 1文字ずつ charCodeAt() で文字コードに変換する
  3. 変換した文字コードを全部足す

と意外とシンプルな実装になっています.

文字列から変換した数値を使って色を決めよう

文字列から変換した数値を % 360 することで 0 ~ 359 で収まる値に変換しています.
n*n をやっているのは, よりランダム性を高めるなのであってもなくても問題ないです.

その値を hsl の 色相(Hue) 部分に指定した値を body.style.backgroundColor に設定することで背景の色が変わるようになっています.

後半の % がついている数値2つを 0 ~ 100 で変換すれば色の濃さや明るさも調整できます.

// 入力した文字列を数値に変換
var n = stringToNumber($input.value);
// hsl 用に 0 ~ 360 に収める
var colorAngle = (n*n) % 360;

// hsl の色相(Hue)部分に文字列から変換した数値を割り当てる
document.body.style.backgroundColor = `hsl(${colorAngle}, 80%, 64%)`;

おわりに

今回は, 文字列を数値に変換し, 更にそれを色に活用するという方法を紹介しました.
DB を使ったりもしていないので, わりと簡単に使えておすすめです!

この Tips は新人時代に, 「プロジェクトを新規で作ったときにユーザーに任意の色を選ばせたい」といった要望を受けて思いついたアイデアでした.

その時のプロジェクトオーナーは, おそらくプロジェクトの一覧の視認性を高めたくてそういった依頼をしたんだと思ったので, ユーザーにとって手間を掛けずにそれを満たす方法はないかと思い提案し, 結果プロジェクトオーナーにもユーザーにも喜んでもらうことができました.

エンジニアは, 要望や目的に対して 本当の課題が何なのかを理解し, 複数のアプローチを持ったうえで最善(効果と費用のバランス)なものを提案できるようになることもすごく大切なことだと思います.

今後も, 色々なアプローチに繋がるような Tips を例を交えて紹介していけたらと思います.

Discussion