好きな画像でラクにグラフ化するJS

前の記事で「できるだけラクにグラフ化するJS」なるものを公開しましたが、基本の仕組みを流用してもうひとつJavaScriptを作ってみました。
グラフの棒部分に好きな画像を好きなカラーで使うことができます。

画像3

※本記事サンプル内のアイコンはFont Awesomeのフリーアイコンを使っています。


こんなHTMLがあるとして…

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
    <dt>30代</dt>
    <dd>73%</dd>
    <dt>20代</dt>
    <dd>22%</dd>
    <dt>10代以下</dt>
    <dd>34%</dd>
</dl>


JSのfunctionを呼び出して、画像やカラーをCSSで指定するだけです。

myChart2("my-chart2");

大部分は「できるだけラクにグラフ化するJS」とかぶるのですが、あらためて概要を。

●読み込んだ画像も含めて、色替えできます。
●PNG、JPEG、GIF、そしてSVGも使えます。
●フォントサイズに合わせて、それなりにバランス調整してくれます。
●もちろんレスポンシブ。
●Edge、IE11でも動きます
(ただしIE11は一部機能が使えません)

デモはこちら。

全画面で見る場合はこちらへどうぞ。

前回のJSを組み替えれば楽勝だろう、と思っていましたが甘かったです。EdgeとIE11により見事にその目論見は粉砕されました。詳しくは後述します。


使ってみたいという方へ

商用・非商用問わずご自由に使ってもらって構いません。
できる限りのチェックはしておりますが、気づいてない不具合が残ってる可能性はあります。使用により生じた一切の損害について理由の如何にかかわらず責任は負いかねます。ご了承ください。


使い方

まず本体のJSファイルを使いたいHTMLに読み込ませます。位置はどこでもいいです。

<script src="chart02.js"></script>


function「myChart2()」を呼び出すコードを入れてください。場所は<body>タグ終了間際などでOKです。外部JSファイルに記述しても構いません。
ただし<head>タグ内での呼び出しは避けてください。空振りします。

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
...
</dl>

...
<script>
   myChart2("my-chart2");
</script>
</body>

引数にはグラフ化したい要素のクラス名を指定します。
上記の例なら要素は<dl>、クラス名は「my-chart2」になります。セレクタ形式ではないので頭にピリオド「.」は不要です。


画像やカラーの指定はCSSで

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
...
</dl>

・奇数番目の子要素がラベル部(上の例なら<dt>)
・偶数番目の子要素がグラフ、数値部(上の例なら<dd>)

それぞれにCSSで設定します。

画像14

以下、詳細です。


使う画像の指定について

数値部分に当たるタグに「background-image」で指定してください。指定できる形式は次の通りです。
 ・PNG
 ・JPEG
 ・GIF(アニメーションGIFは除く)
 ・SVG(IE11では使えません)

ファイルの作り方によっては読み込めないものもあるようです。その場合は設定を変えて再書き出しする等をお試しください。

<使用する画像例>

画像5

.my-chart2 > dd{
    background-image: url(person.png);
    ...
}
...

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
...
</dl>

画像4

【注1】別ドメインにある画像を指定することはできません。

【注2】ローカル環境では動作しません。
PC内のファイルを直接ブラウザで開いても動きません。サーバにアップロードして確認してください。

上記2つの【注】はブラウザのセキュリティ制限によるものです。
JSの中で画像をゴチャゴチャと操作しているのですが、その機能はセキュリティ的に安全な環境上でのみ動作する仕様になっているためです。

CSSなので、各行それぞれに異なった画像も指定できます。

.my-chart2 > *:nth-child(2){
    background-image: url(grin.png);   
    ...
}
.my-chart2 > *:nth-child(4){
    background-image: url(flushed.png);
    ...
}
.my-chart2 > *:nth-child(6){
    background-image: url(dizzy.png);
    ...
}
...

<dl class="my-chart2">
    <dt>ウケた</dt>
    <dd>56%</dd>
    <dt>ビックリした</dt>
    <dd>43%</dd>
...
</dl>

画像14


カラーの指定について

文字部分は「color」で、画像カラーおよびラベル背景カラーは「background-color」で指定してください。
文字部分の「color」については、直接指定がなければ継承しているCSSが反映されます。もちろん各行異なったカラーも指定できます。
なお、カラー指定にrgbaや16進8桁などの透過は使えません。

.my-chart2 > dt{
    color: #000000;
    background-color: #dbbe7c;
}
.my-chart2 > dd{
    background-image: url(person.png);
    color: #dbbe7c;
    background-color: #dbbe7c;
}
...

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
...
</dl>

画像14


画像の色を変えずにそのまま表示したい

もちろんできます。
数値部分タグの「background-color」を省略すると、画像の色は変わらずに元ファイルのまま表示されます。

.my-chart2 > dd{
    background-image: url(tea.png);
    color: #00863c;
    /* background-colorは指定しない */
}
...

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
...
</dl>

画像9


画像カラーは透明部分以外を塗りつぶします

■ PNG、GIF
画像の色替えをする場合は透過の形式にしてください。
不透明ピクセルに全部着色しますので、透過でない画像を使用すると単に塗りつぶされた矩形になります。

画像10

画像11

■ JPEG
JPEGには透過がないので、カラー指定するとこれも上の例のように矩形で塗りつぶされます。JPEGの場合は「background-color」の指定は外してください

■ SVG
【注】IE11ではSVGは使えません。

オブジェクトすべてを塗りつぶしますので、ヌキにしたい場合はIllustratorで言うところの複合パスの状態にしてください。

画像18

【注】について、SVGの表示自体はIE11でも可能なのですが、今回のこのJSで実装した機能には対応していないという意味です。


ラベル背景のベタが邪魔だ!

外せます。
これはCSSではなく、function引数のクラス名の後にオブジェクト形式でオプション設定できるようにしています。
次のように「labelbg」というプロパティ名で「false」を指定してください。

myChart2("my-chart2",
    {
        labelbg: false
    }
);

画像13


グラフの先端をどうするかを選べます

デフォルトでは次のようになっています。

画像14


これを次のようにしたい場合は、オプションに「cutoff」というプロパティ名で「true」を指定してください。

画像15

myChart2("my-chart2",
    {
        cutoff: true
    }
);


全体のサイズは自動調整です

各パーツのサイズは親要素に指定または継承されているCSSのフォントサイズが基準になります。フォントサイズを変えれば勝手に変わります。画像については縦長でも横長でも自動でバランス取るようにしてます。

.my-chart2{
    font-size: 1.5rem;
}
...

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
    <dt>40代</dt>
    <dd>43%</dd>
...
</dl>

画像15

全体の幅も適用されているCSSに従います。レイアウトは自動で整えますのでレスポンシブ対応する必要もないです。

画像16


画像のサイズ感だけを変えたい

オプションの「imagesize」に1〜5の数字(小数もOK)を指定することでサイズ感を変更できます。この値は親要素のフォントサイズに対しての相対値で、デフォルトは3です。

myChart2("my-chart2",
    {
        imagesize: 1
    }
);

画像17


画像の間隔を調整したい

オプションの「interval」に0〜1の数字を指定することで変更できます。この値も親要素のフォントサイズに対しての相対値で、0が間隔なしです。デフォルトは0.3です。

myChart2("my-chart2",
    {
        interval: 0
    }
);

画像19


グラフ化させるタグはなんでもいい

サンプルでは<dl>を使っていますが、
 1. 親ブロックの中に子要素が偶数個ある
 2. 子要素の偶数番目のテキストに数字が入っている
この条件を満たせば、特殊なものでない限りタグはなんでもOKです。<ul>と<li>でも、<p>と<span>でも、<div>だけの入れ子でも動きます。

2.については、数字さえ入っていれば単位が頭でも後ろでも2バイト文字でもOK。カンマ打っても構いません。
ただし、小数点があれば小数としてグラフ描画の計算をします。

<ul class="my-chart2">
   <li>アップルパイ</li>
   <li>67%</li>
...
</ul>

<p class="my-chart2">
   <span>エクレア</span>
   <span>¥220</span>
...
</p>

<div class="my-chart2">
   <div>超特大ホールケーキ</div>
   <div>13,200円</div>
...
</div>


その他のCSS

余白やボーダー・背景色・幅など、これもよほど特殊なものでない限り適用OKです。

.my-chart2{
   width: 80%;
   padding: 10px;
   border: 5px solid #770000;
   border-radius: 10px;
   background-color: #ffefbc;
}
...

<dl class="my-chart2">
    <dt>50代以上</dt>
    <dd>56%</dd>
...
</dl>

画像18


ライブラリ依存しません

JQueryはもちろん、他に必要なライブラリはありません。単独で動きます。


他ライブラリとのバッティング

できるだけページ内で同時に使用している他のライブラリやCSSの邪魔はしないよう作ってあります。
逆にリセットCSSなどの影響もほぼ受けません。

ただし、当たり前ですがこれらを100%保証することはできません。JSやCSSの書き方・組み合わせによっては何でも起こり得ますので。


Edge・IE11を見捨てない…つもりだったんですが

「できるだけラクにグラフ化するJS」ではなんとかIE11を救い出しましたが、今回はSVG対応だけ断念しました。
無理矢理やろうと思えば出来なくはないなんですが、その労力に見合わないのでやめました。結構な追加処理が必要でしたしPNGなどは使えるようにしておいたので。

あとEdgeにもまんまとやられました。最初はCSSの「mask-image」を使って実装するつもりだったんですが、このプロパティ、IEはもちろんEdgeでも使えないんですよ…。やむを得ず画像を直接操作するハメになりました。

そういうわけで、Edge・IE11を対象に入れるというだけでメチャクチャ面倒くさい組み方しています。無視すればコード分量は半分以下で終わったんじゃないでしょうかね。


最後に

前回以上にチカラ技になってしまいました。
一旦頭の中で出来上がったものは形にしないと気が済まないので、ゴールにたどり着いたということで良しとします。

単なる思いつきと勢いだけで作ったこのグラフシリーズ、他にも作ってみたい案はあります。
ですが、のめり込んでしまうと他のことに使う時間がなくなるしJSをメインの仕事としているわけでもないので、しばらく寝かせることにします。

汎用的なグラフなんかは使い道ありそうですけどね。時々こういうものを作ると必ず得るものはあるので、気が向けばまたやろうと思います。