logo-idv ico_pp

デザイナーがVue.jsで大きなカラーピッカーを作ってみた

デザイン

こんにちは。デザイナーのKです。

本記事では、JavaScriptフレームワーク「Vue.js」の実験+学習を兼ねて行った、オリジナルカラーピッカー作成の概要をご紹介します。

2017-09-20 15.33.23
カラーピッカーとは上図のような、色を調整したりカラーコードを拾ったりするためのツールです。
大抵のデザインツールにはデフォルトで付属しているので、わざわざ自作する必要は無いのですが、かねてから自分専用の「痒いところに手が届く」カラーピッカーが欲しかったことと、機能・規模的にVue.jsの導入教材としてちょうどいいサイズに思い、開発に挑戦しました。

求める機能はこんなかんじです。

  • でかい
  • 手軽に起動
  • CSSコーディングに最適化

DEMO

早速ですが成果物をご覧ください。Chrome以外での動作は保証しません。

See the Pen Big Color Picker by makudo (@makudo) on CodePen.

動作のあやしいところはあるものの、おおむね一般的なカラーピッカーと同等の挙動になっているはずです。
大きさはAdobeのカラーピッカーのおよそ2倍弱で、存在感のあるサイズではないでしょうか?
大きいと何が嬉しいのかと言うと、単純に気分がいいというだけです。大きいからより細かく色指定ができるというわけではありません。

工夫したポイントについて図解します。

picker_function

上図の赤枠部分が自分にとっての「痒い所に手が届く」以前から欲しかった機能です。
ささやかな機能ですが、これによりCSSコーディングの効率が若干向上します。

大したツールではありませんが、「冷蔵庫の残り物だけでサッと美味しい夜食を作れた」的な、
自己満足のいく仕上がりとなりました。

Vue.jsとは

vuejs

Vue.js

Vue.jsとはインタラクティブなUIを構築するためのJavaScriptフレームワークです。
DOMとデータの同期のためにリアクティブなデータバインディングを提供することが特長の1つです。

リアクティブとは

正確な定義を無視して、かなり大雑把に説明すると、この記事で扱う「リアクティブ」とは

「Aを変更したら連動してBが変わる」
「Bを変更したら連動してAが変わる」

という挙動・仕組みのことを指します。
よく使われる例えは、「エクセルでセルの値を変更すると連動して別のセルの値が変化する」という挙動です。

excel

カラーピッカーツール開発においては

「カーソルの位置に応じてカラーコードの値が変化する」
「カラーコードの値に応じてカーソルの位置が変化する」

という挙動の設計ために「リアクティブなデータバインディング」が役立つはずです。

jQueryじゃだめなのか?

実はこのツールは、当初はjQueryで開発していましたが、途中で断念しています。

基本的な機能は実装できたのですが、私の能力では複数のカラーコードとカーソルのリアクティブな挙動の設計は難易度が高く、
「これを動かしたら連動してここが変化して…」という動作を追加していくうちにイベント管理が死ぬほど煩雑になり、挫折しました。

もちろん、jQueryでもしっかり設計すれば問題なく実現できるはずですが、
リアクティブなデータバインディングはVue.jsのほうが圧倒的に簡単でした。

※ 正確には「リアクティブな挙動」と「リアクティブなプログラミング」は別の概念だそうですが、ここでは簡便のために敢えて混同しています。

見た目を作る

挙動を実装する前に、HTMLとCSSで見た目を作ります。

隠し課題として、今回は画像を一切使わずにCSSだけで表現できないかチャレンジしてみました。
自己満足が理由の大半ですが、CSSのみで構築することで今後の取り回しやメンテナンス性にも恩恵がもたらされるはずです。

予想していた以上に苦戦しましたが、なんとかHTML+CSSだけで組むことができました。
無駄なこだわりを発揮してAdobeライクなスキンを採用。

See the Pen Big Color Picker by makudo (@makudo) on CodePen.

特に苦労したのは彩度+明度を調整する正方形の領域です。
ここは複雑なグラデーションでできており、CSSのみでの表現は困難に思われましたが、
よく観察すると下図のような構成になっていることに気づきました。

picker_const

これならCSSだけでなんとかできそうです。
結果、以下のように指定して実現しました。

グラデーション部分は固定で、background-colorの変更で色相変化に対応できます。

Vue.jsの準備

※この記事は私なりのVue.jsの使い方、気づいたポイントなどの紹介がメインで、Vue.jsそのものの解説は主目的としていません。用語や説明内容に誤りが含まれている可能性は高いと思われますので、予めご容赦ください。

最小構成を用意

空のHTMLファイルを用意します。
手軽に使いたいのでVue.jsはCDNで読み込みます。

Vue.jsで構築する領域(コンテナー)を用意します。

以下のようにVueインスタンスを作成し、elオプションに上記コンテナーのidを指定してVueインスタンスを紐付けます。

これで開発の準備ができました。

Vue.js Devtools

事前にVue.jsデバッグ用のChrome拡張をインストールしておくと便利です。

Vue.js devtools

基本的な使い方

data, methods, computed, templateオプション

このカラーピッカーツールでは上記4種類のオプションを利用しています。

私はそれぞれ以下のような理解のもと使い分けています。

オプション 説明
data 変数置き場。Vueインスタンス内で利用する変数(stateというそうです)を定義。
オブジェクトを返す関数として記述する。
methods メソッド置き場。イベント発火の処理、引数がある処理、戻り値の無い処理を記述する(ことにしている)。
computed 算出プロパティ置き場。計算結果を返す。変数のように使う関数。methodsよりも処理効率が良いらしい。
devtoolsで値の参照ができるのでここに書ける処理はなるべくここに書く
template HTMLを書く場所。この内容がelオプションで指定したコンテナー内に描画される。

methodscomputedについての解釈が怪しいですが、一応このような区別で利用しています。

以下は説明のためにサンプルとして作ったリンゴの値段計算機です。
120円 × 追加数 × 消費税8%の値段を表示します。

See the Pen Apple Calc by makudo (@makudo) on CodePen.

  • template部で、{{ }} 記法でdatacomputedの値を参照できます。値の変更を検知して動的に書き換わります。
  • v-onディレクティブを使うとイベントを登録できます。v-on:click="plus1"で「クリックされたらplus1メソッドを実行」となります。
  • methodscomputedstateを参照する場合は頭にthisを付けます。
  • {{result}}にはcomputedでの計算結果が返ります。

jQueryのように、DOM要素を直接操作するのではなく、dataの監視と検知が自動的に(?)行われ、処理が実行されることがポイントです。

カラーピッカー解説

前置きが長くなりましたが、ここからカラーピッカーの主要部分について、いくつかピックアップして解説します。

支配的rgbオブジェクトで全体を管理

jQueryでの開発時の失敗は、カーソルの位置やカラーコードを決定する際に、統一的に管理されているデータを参照するのではなく、場当たり的・その場しのぎ的な処理を重ねてしまい、全体が混乱したことでした。

それを踏まえ、今回のツールでは、全ての要素のふるまいを決定するrgbオブジェクトを用意しました。

どのような変更処理も必ずこのオブジェクトと手続きが必要、という官僚的な仕組みを採用することでイベント処理が増大しても混乱が軽減できるはずです。

picker_concept1

しかしうまくいかなかった

カーソルの座標の制御にはHSV(Hue(色相)Saturation(彩度)Value(明度))という色モデルを利用し、
適宜RGBに変換、またはその逆をする必要があります。

そのHSV色も常に支配的rgbを参照して管理したかったのですが、
RGB←→HSV変換がどうしてもうまく行かず(※)、結局rgbオブジェクトと同等の支配力を持つhsvオブジェクトを用意せざるをえませんでした。

※ 例えばh:360 s:0 v:0 と h:100 s:100 v:0 はHSV的には違う値だが、RGB的にはどちらも#000000であり、状況によってHSV→RGB変換の内容が変わってしまうという問題を解決できなかった

そして、rgbに変更が発生したらhsvも変更する(またはその逆)という処理を手動で実装しています。
Vue.jsのうまみを減衰させる手続きですが、他に妙案が思いつきませんでした。

picker_concept2

rgbオブジェクトから色を表示

現在色のプレビューと16進数コードの表示は以下のように書きます。
単純に、rgbの値を16進数に変換してHTMLに突っ込むということをやっています。

v-bindディレクティブを利用すると要素の属性で式を利用できます。

クリック座標からカーソルと16進数コードを変更

カラーピッカーをクリックしたら、座標を元に色を計算するという処理を作ります。

カーソル位置の制御にはHSV色を使う必要があると説明しましたが、それは、HSVがカラーピッカーの値と下図のように対応しているからです。

picer_sv

X軸とY軸に対応しているので、クリック座標からそれぞれの色要素への変換ができます。

以下のコードでこのような処理を行います。

  1. クリックでcolorSelectメソッド実行
  2. クリック座標からhsv(のsとv)を変更 → hsvの値をもとにrgbを変更
  3. hsvの変更を検知してカーソルの位置が変化 & rgbの変更を検知してプレビュー色&コードが変化

※微調整や例外処理などの記述は削除しています。

  • methodsではdataの変更を行うだけ
  • computeddataの値からカーソルの位置を計算する
  • templateではイベントの登録とcomputedの参照を設定する

というように処理を切り分けられるため、非常にスッキリと記述することができます。
特にmethods部分でDOMのことを考える必要が無いということが、大きなストレス軽減となりました。

その他の処理

上記の考え方の応用で以下の処理も実装できます。

  • 色相操作
  • ドラッグ操作
  • 16進数コード入力
  • その他カラーコード及び不透明度操作
  • 上下キーで値の変更
  • 例外処理

完成

See the Pen Big Color Picker by makudo (@makudo) on CodePen.

そしてさらにこれをこねくり回してブックマークレットを作りました。よろしければご笑納ください。

デザイナーにとってのVue.js / jQueryとの比較

複数の要素が相互に絡み合うような複雑な処理はjQueryよりもVue.jsの方が圧倒的に楽

  • 例:入力フォームのインタラクションやリアルタイムバリデーション
  • 例:複雑な条件分岐が必要な検索パネル

導入時の心理的ハードルが高いが、一度Vue.jsの作法を把握してしまうとむしろjQueryより難易度が低い

  • 「書く場所が決まっている」ことがかなり嬉しい。DOMの制御とロジックを完全に分離して書けることによる心理的恩恵が想像以上に大きい。
  • 「.js-◯◯◯」とか「.is-◯◯◯」みたいな慣例的テクニックによるクラス命名が必要ない。

ちょっとしたDOM操作であればjQueryで十分

  • ボックスのアコーディオン展開とか、モーダル表示、軽いアニメーション程度の実装であればjQueryのほうが楽だし便利。

HTMLの管理・修正に混乱が発生する可能性がある

  • HTML記述箇所が分散して、統一したHTMLソース管理に支障をきたすおそれ。
  • Vue.jsの記法を理解していないとHTML修正のハードルが高い。
  • BladeやSmartyなどのPHPテンプレートエンジン記法との競合・混乱に注意が必要

Vue.js導入によるメリット/デメリットはケースバイケースで、既存プロジェクトへの安易な導入はデザイナーへの負担が高そうです。
とはいえ、エンジニアが書いたVue.jsに手も足も出ない、という状況は避けるべきでしょうし、教養として学習しても損はないと感じました。

なにより面白いです。

最後に

この記事の執筆中、昨今のカラーピッカー事情はどうなっているだろう? と気になり、
Goolgleで「カラーピッカー」と検索した結果、こんなツールが表示されて度肝を抜かれました。

google

さすがです。とても高機能です。。
こんなものがあるのなら敢えて作る必要もなかったかもしれませんが、
ともあれとても勉強になりましたし、自分で作ったツールには愛着があります。

今回は本当に基礎的な機能しか利用しませんでしたが、
機会があればコンポーネントやルーティングを駆使したSPAの開発など携わってみたいものです。

とりとめのない長文にお付き合いいただき、ありがとうございました。

参考サイト

以下のCodeGridの記事は第2回目以降は有料ですが、丁寧かつ簡潔に解説されており、大変勉強になりました。

これから始めるVue.js 2.0 – CodeGrid
ライトに使うVue.js – CodeGrid

Vue.js公式日本語ガイド

執筆者プロフィール

UXデザイン推進室所属のデザイナー。デザインとエンジニアリングの境界領域に関心を持っています。
冷凍餃子を蒸し焼きする時は、水でなく熱湯を注ぐと綺麗に焼けるというTIPSを授かり、以来負け無しです。