数週間前、Boxy SVGの無料のベクターエディターを使って、SVGで次のStar Trek vs. Star Warsチャートを作る方法について書きました。
この記事では、SVGのきれいでうまく描けるメリットについても触れました。今回の記事では、そのアイデアについてもう少し深掘りしてみます。デザインとUXのカテゴリーなのは分かっていますが、ときにはより良いデザインのためにコードレベルまでコントロールしなければなりません。これからSVGマークアップの中身をあれこれ見ていくことになりますが、きっと役に立つ何かを得られるでしょう。
SVGを使った実験をするときは、以下の方法がベストです。
- Boxy SVGで何か簡単なものを描いて保存し、
- 好きなテキストエディター(Brackets、Atom、Sublimeなどなんでも可)に読み込み、
- コードをCodepen.ioのHTMLパネルの中に直接コピー&ペーストすると、Result画面の中にレンダリングされます。
ここまで準備すれば、変更を加えると、どのようなことが起こるかが分かります。これは、Codepenにペーストされた私のオリジナルのStar Trek vs. Star Wars チャートです。
良いSVG=整理されたSVG
ここで少しコードエディターに戻って、SVGチャートの基本的な構造に目を向けてみましょう。 先頭には、この記事の後半で使う再利用可能なリソースを含む<defs>タグのかたまりがあります。特に次のようなタグが目立つはずです。
- グレーの背景にある「光」のグラデーション、そして
- 背景として使うグリッドパターン
<defs>の下にある残りのドキュメントは簡単に理解できるものです。
- ハイライトされている、バックグラウンドにある四角(<rect>)はチャートのキャンバスになる
- グリッドパターンのあるチャートのボディ(<rect>)
- チャートのタイトル(<text>)
- 「Star Wars」を示す黄色い折れ線グラフ(<path>)
- 「Star Trek」を示す青い折れ線グラフ(<path>)
- 各線を表す2つのラベル(<text>)
- y軸の目盛り(<text>)を含むグループ(<g>)
- x軸の目盛り(<text>)を含むグループ(<g>)
それほど多くはありませんよね?
しかし、軸目盛りの2つのグループをじっくり見てみると、繰り返しがたくさんあることに気づきます。
<text y="430" x="40" style="text-anchor: middle; fill: rgb(103, 102, 102); font-size: 12px;">1960</text>
<text y="430" x="118" style="text-anchor: middle; fill: rgb(103, 102, 102); font-size: 12px;">1965</text>
<text y="430" x="196" style="text-anchor: middle; fill: rgb(103, 102, 102); font-size: 12px;">1970</text>
もしこれが、何度も繰り返されているインラインプロパティを表わすHTMLだったら、CSSに移してクラスと入れ替えた方がよいですよね。まったく同じことをSVGでやらない手はありません。
先頭にすでに<style>ブロックがある<defs>セクションでは、次のように新たなCSSルールを加えられます。
.y-axis text {
text-anchor: middle;
fill: rgb(103, 102, 102);
font-size: 12px;
}
これによって、上のようなテキストノードを次のようにもっとコンパクトにできます。
<text y="430" x="40">1960</text>
<text y="430" x="118">1965</text>
<text y="430" x="196">1970</text>
このコードは抜群に内容が分かりやすいだけでなく、1か所から、より小さなファイルですべてのy軸の目盛りの色を変えられるようになります。Win-Win-Winですね。
コードエディターの検索・置換を使えば、ファイルをきちんと整理できます。チャートの中の折れ線グラフのラベルスタイルを<style>で決めることもできます。新しいCSSのクラスを作って、それをラベルテキストに加えます。
.label-starwars {
white-space: pre;
font-size: 15px;
fill: rgb(253, 200, 39);
word-spacing: 0px;
}
SVG要素の「x」や「y」の値はCSSに移せないことを忘れないでください。しかし、その他のすべてのプロパティはクラスに移動できます。「fill」または「stroke」(上の例のように)といったCSSの仕様にないものさえ含まれます。
これは同じいくつかのSVGファイルを新しいCSSクラスで読みやすく整理したものです。
しかし、クリーニングに関する記事ではありませんので、チャートについてもっとクールかつ役立つ方法を説明します。
さらにスマートなSVGの作り方
SVGを使ううえでもっとも重要なメリットは、間違いなく「拡張性(scalability)」ではないでしょうか? だって、拡張性こそが「SVG」の「S」を意味するものなのですから。アイコンをとてもシャープで鮮明なままで、そのサイズを40pxから400pxへといとも簡単に拡張できます。
しかし、これにも限界はあります。
より小さなスクリーン上にフィットするようにチャートを縮小できたからといっても、そのチャートが現実的に役立つとは限りません。ラベルが小さすぎて読めないようなら、いくらシャープであっても意味がありません。
上のチャートで分かるように、チャートの幅を約500px未満にすれば、テキストはすぐに判読不能になります。
レスポンシブSVGならできます!
まさに、これからSVGの中で使うCSSメディアクエリーによって、HTMLやCSSでのこの種の問題に対処できます。ここまでSVGのCSS化に時間を費やしてきましたが、ここでそのメリットを享受できます。
チャートが幅500px未満になったときのフォントサイズを決定するために、<style>ブロックの中にCSSメディアクエリーを追加できます。次のようになります。
@media (max-width: 500px) {
.label-startrek, .label-starwars{
font-size: 170%;
}
.y-axis text {
font-size: 130%;
}
.x-axis text {
font-size: 130%;
}
}
結果は下のようになります。
すばらしい! おかげでチャートがより小さくなっても、x軸・y軸の目盛りは前よりは読みやすくなっています。しかし、これもまた少し込み合った感じで見た目が良くありません。
もしここで、現在のラベルをもっと読みやすくするため偶数番目のラベルを全部隠したらどうなるでしょうか。もちろん小さなデバイスでもユーザーのUXは良くなります。
「hide-on-small」という名の新たなCSSクラスを作り、これをメディアクエリーに追加します。
.hide-on-small{
display: none;
}
… そしてこのクラスを偶数番目の数字のすべてに適用します。
<text y="430" x="40">1960</text>
<text y="430" x="118" class="hide-on-small">1965</text>
<text y="430" x="196">1970</text>...
Update: 2016年5月28日
記事公開後にAmeliaが指摘してくれたように、各軸のそれぞれの偶数番目の数字を取り扱うにはもっと洗練された方法があります。それがCSS nth-of typeです。これさえあれば大丈夫です。
.x-axis text:nth-of-type(2n),
.y-axis text:nth-of-type(2n) {
transition: opacity 1s ease-in-out;
opacity: 0;
}
とはいえ「.hide-on-small」と呼ばれるクラスを使うことは、汎用性の高いものを作るときには十分役立ちます。
実際にはこのように見えます。
最後に
まだまだ洗練されていないデモでしたが、特にグラフ、チャート、インフォグラフィックスの改善に使える、レスポンシブSVGの可能性ついて理解できたと思います。
SVGの中でメディアクエリーを使った実験にCodepenを使うのは楽しいものです。キーボードを叩きながら、自分の作業がその場で進展していくのが見られるので、やりがいが感じられる方法でしょう。
すでに練習は終わったので、CodepenのCSSウィンドウへCSSを直接書き込んで構いません。必要であればSaasやLess、Stylusといった便利なものをSVGの中で統合して使えます。
とはいえ、スタティックなCSSが完成したあとに、SVGの<style>ブロックの中に移動することをおすすめします。この方法であれば、SVGは自己完結型のユニットのためCSSファイルから分離されてもレンダリングは中断されません。
レスポンシブSVGを作るメリットはほかにもあります。レスポンシブSVGは表示されるデバイスに対する適応能力が高く、また、レイアウトの中でどこに置かれても、うまく適応します。
記事のリストビュー(結局たった5kなのですが)で使われるとき、上のグラフがグラフ自体のサムネイルにもなることを意味します。おそらく150px未満でレンダリングされるときは、テキストを全部非表示にしてチャートの中に折れ線だけを残した方が良いかもしれません。
まったく同じSVGが「control panel view」の中では違って見え、上のCodepenのように複数のチャートを表示します。どのチャートも、マウスを重ねた途端に詳細に拡大してフォーカスします。
注意:デモは変化を強調するためにCSSへの移行に焦点を絞りましたが、少し大げさにやりすぎたかもしれません。なんだか見るだけで酔ってしまいますね。とはいえ基本的な原則については伝えています。
レスポンシブSVGの可能性には終わりがありませんが、コードは手で書く必要があります。手書きの代わりにここまでうまくやってくれるツールはありません。
後日、SVG内でメディアクエリーを使ったさらに洗練された方法を紹介する予定です。
(原文:Make Your Own Responsive SVG Graphs & Infographics)
[翻訳:島田理彩]
[編集:Livit]