サンプルコード付き!CSSとJavaScriptで棒グラフを作ってみよう!

数値に関する情報は、文字だけでなくグラフにして表すと格段にわかりやすくなります。 管理画面や、アンケートの集計結果など、ウェブページ上でも数値情報を取り扱うことは少なくありません。今回は、CSSとJavaScriptを用いて、グラフを作成する方法を初学者向けに解説します。

棒グラフの作り方

スタンダードな横棒グラフのマークアップ例のサンプルが以下になります。

html

<p>
  Q: ●●についてどう思いますか?
</p>
<div class="container">
  <div class="item item1">
    <span class="item_label">良い: 15%</span>
  </div>
  <div class="item item2">
    <span class="item_label">どちらとも言えない: 80%</span>
  </div>
  <div class="item item3">
    <span class="item_label">悪い: 5%</span>
  </div>
</div>

css

.container {
  background-color: #c5d1d8;
  height: 160px;
  width: 100%;
  display: flex;
  flex-direction: column; /* 要素を縦に並べる */
  justify-content: space-evenly; /* 要素を均等間隔に分散させる */
}

.item {
  box-sizing: border-box;
  background-color: #FFFFFF;
  padding: 4px;
}
/* 項目のキャプションが折り返してしまわないように設定 */
.item_label {
  white-space: nowrap;
}
/* 各要素の長さ */
.item1 {
  width: 15%;
}

.item2 {
  width: 80%;
}

.item3 {
  width: 5%;
}

body {
  padding: 8px;
  font-size: 12px;
  background-color: #20262e;
}

p {
  color: #EEEEEE;
}

動作デモURL:https://jsfiddle.net/maiko_ampersand/u1tvg1ck/

この例ではFlexboxを用いて項目を作成しています。 これにより、項目の増減やグラフのコンテナーの大きさの変更があった場合にも大きく見た目を崩すことがない形で作成することや、表示順序の入れ替えが可能です。

ポイントとなるプロパティについて

このような棒グラフを作成する上でポイントとなるプロパティについて解説します。

justify-contentプロパティ

このプロパティのMDNのリファレンスはこちらです。

このプロパティは、要素をどのように配置するかを定義するためのものです。いくつか使用できる値の例と動きを以下に記載します。

要素を集める

始端に集める flex-start

justify-content: flex-start; /* 要素を始点に集める */

デモ:https://jsfiddle.net/maiko_ampersand/Lodrfw91/34/

中央に集める center

justify-content: center; /* 要素を中央に寄せる */

デモ:https://jsfiddle.net/maiko_ampersand/Lodrfw91/35/

終端に集める flex-end

justify-content: flex-end; /* 要素を終端に集める */

デモ:https://jsfiddle.net/maiko_ampersand/Lodrfw91/36/

要素を分散させる

最初のアイテムは始端に接する。最後のアイテムは終端に接する space-between

justify-content: space-between; /* 要素を均等間隔に分散させる */

デモ:https://jsfiddle.net/maiko_ampersand/8bwm4oL8/2/

アイテムは両側に半分のサイズのスペースを持つ space-around

justify-content: space-around; /* アイテムは両側に半分のサイズのスペースを持つ */

デモ:https://jsfiddle.net/maiko_ampersand/8bwm4oL8/14/

各アイテムの周囲に均等なスペースを置く space-evenly

justify-content: space-evenly; /* 各アイテムの周囲に均等なスペースを置く */

デモ:https://jsfiddle.net/maiko_ampersand/8bwm4oL8/15/

要素の並び順を設定する flex-directionプロパティ

このプロパティのMDNのリファレンスはこちらです。この要素を用いて積み上げグラフのような見た目にすることもできます。

要素を横並びにする row;

flex-direction: row; /* 要素を横に並べる */
justify-content: space-evenly; /* 要素を均等間隔に分散させる */

デモ:https://jsfiddle.net/maiko_ampersand/8bwm4oL8/16/

Flexboxを使用する上での注意

2018年4月現在、Flexible Box Layout Moduleはほぼすべてのモダンブラウザ環境で動作します。IE9以下のレガシーな環境では使用できないため、業務上の都合などでサポートしなくてはいけない場合は注意が必要です。

参考:https://caniuse.com/#feat=flexbox

JavaScript(jQuery)と組み合わせる

今までの例はHTMLとCSSのみを使用してきましたが、JavaScriptを用いてダイナミックなグラフを作成してみましょう。

ここではライブラリとしてjQueryを用います。jQueryとはJavaScriptそのままの状態で記述すると煩雑になってしまう処理をより平易に記述できるようにと2006年に開発されたライブラリです。

そのままの状態で記述すると煩雑になってしまう処理とは例えばどういったものかというと、ブラウザごとに異なった記述をしなければならないような処理や、Ajax処理などが該当します。

jsonデータからグラフを作成してみる

話を戻して、グラフの作成について触れていきましょう。上述のCSSでグラフを作成する例では、予め各要素の横幅を設定しておく必要がありましたが、APIから取得した値の表示などに対応をするために、JavaScriptと組み合わせて、動的にグラフを表示してみます。

実装例

<div class="container"></div>
.container {
  background-color: #c5d1d8;
  height: 200px;
  width: 100%;
  display: flex;
  flex-direction: column; /* 要素を縦に並べる */
  justify-content: space-evenly; /* 要素を均等間隔に分散させる */
}

.item {
  box-sizing: border-box;
  background-color: #FFFFFF;
  padding: 4px;
}

.item_label {
  white-space: nowrap;
}

body {
  padding: 8px;
  font-size: 12px;
  background-color: #20262e;
}
$(function(){
	// 何らかの投票データの配列
	var voteData = [
  	{ label: '良い', point: 300 },
  	{ label: 'どちらかといえば良い', point: 800 },
  	{ label: 'どちらかといえば悪い', point: 240 },
  	{ label: '悪い', point: 100 }
  ];
  
  // 投票の合計値(全体の100%となる値)を求める
  var total = voteData.reduce(function(a,b){ 
  	return {point: a.point + b.point }
  });
  
  // 投票データから項目を作成してコンテナに追加する
  $.each(voteData, function() {
    // 項目要素
  	var $item = $('<div>').addClass('item');
    // 項目のラベル
    var $itemLabel = $('<span>').addClass('item_label');
    // 項目投票数の全体のうちの割合を出す
    var percentage = (this.point / total.point) * 100;
    // 項目要素の長さを割り出して設定する
    $item.css({
    	width: percentage + '%'
    });
    // ラベルに文字列を設定する
    $itemLabel.text(this.label + ' : ' + this.point + '票');
    // 項目にラベルを入れる
    $item.append($itemLabel);
    // 項目をコンテナに入れる
    $('.container').append($item);
  });
});

デモ:http://jsfiddle.net/maiko_ampersand/bmhdughg/38/

項目の順番で表示を並び替える

Flexbox要素はorderプロパティで表示順序を入れ替えすることができます。以下のサンプルは、リンクを押すと項目の横幅順に並べ替える例です。必要に応じて、入れ替える順序にするための項目と評価基準を変更することで、思い通りに並び順を変更させることができます。動きについてはデモURLから御覧ください。

<div class="container">
<div class="item item1">&nbsp;</div>
<div class="item item2">&nbsp;</div>
<div class="item item3">&nbsp;</div>
</div>
<a href="#" id="sort_asc">多い順に並べ替える</a>
<a href="#" id="sort_desc">少ない順に並べ替える</a>
.item1 {
width: 15%;
}
.item2 {
width: 80%;
}
.item3 {
width: 5%;
}
$(function(){
// 並べ替え対象の項目
var $items = $('.item');
// 多い順に並べ替えるリンクのクリック
$('#sort_asc').on('click', function (e) {
e.preventDefault();
// 横幅が大きい順にソート
$items.sort(function(a,b){ return $(a).width() > $(b).width() ? -1 : 1 });
// ソートした順にorderプロパティを設定する
$items.each(function(i) {
$(this).css({ order: i });
});
});

// 少ない順に並べ替えるリンクのクリック
$('#sort_desc').on('click', function (e) {
e.preventDefault();
// 横幅が狭い順にソート
$items.sort(function(a,b){ return $(a).width() > $(b).width() ? 1 : -1 });
$items.each(function(i) {
$(this).css({ order: i });
});
});
});

デモ:http://jsfiddle.net/maiko_ampersand/Lodrfw91/24/

グラフの項目をアニメーションさせてみる

アニメーションを実装する方法は色々ありますが、今回はCSS Transitionを使う形でグラフの項目を動かしてみます。CSS TransitionはCSSプロパティの状態の変化時間と挙動を定義することができます。

以下のサンプルでは、itemクラスのwidth要素にトランジションを設定し、widthを変化させるクラスの付け外しを行うことで表示時のアニメーションを実現しています。

<div class="container">
<div class="item item1 hidden"></div>
<div class="item item2 hidden"></div>
<div class="item item3 hidden"></div>
</div>
<a href="#" id="toggleItem">表示を切り替える</a>
.item {
box-sizing: border-box;
background-color: #FFFFFF;
padding: 4px;
transition: width 1000ms 0s ease;
}

.hidden {
padding: 0;
width: 0;
}
$(function(){
// グラフの項目
var $items = $('.item');
// 表示を切り替える
$('#toggleItem').on('click', function(){
$items.toggleClass('hidden');
});
});

デモ:http://jsfiddle.net/maiko_ampersand/Lodrfw91/37/

より複雑なグラフを使いたい場合はChart.jsがおすすめです

この記事では学習のための簡単なサンプルを紹介してきましたが、実際の業務ではもっと複雑で高機能なグラフが求められることもあるかと思います。そのような場合にはグラフのライブラリを用いるのが良いでしょう。

グラフを取扱できるライブラリはいくつか存在しますが、その中でも人気が高く、扱えるグラフの種類も豊富であるchart.jsを紹介したいと思います。JavaScriptが全くの初心者の方だと少しだけとっつきづらさを感じるかもしれませんが、非常に高機能で見た目も綺麗なので、グラフを必要とするシーンに採用する価値は高いと思います。

取扱できるグラフの種類が豊富

Chart.jsでは沢山の種類のグラフが取扱できます。 棒グラフ、線グラフ、面グラフ、円グラフ、レーダーチャート、散布図などが揃えられています。公式の豊富なサンプルがありますので、そちらをご覧ください。

chart.jsで実装できるグラフの一例

ほとんどの環境で問題なく動作させられる

Chart.jsのグラフは画面リサイズ・レスポンシブ対応がされているため、端末による画面の大きさの違いを気にせず採用することができます。また、現状のほぼすべてのモダンブラウザ(IEは9以降)環境で動作することも大きな魅力です。

終わりに

いかがでしたでしょうか。 この春からお仕事でWeb関係の作業を始める方もいらっしゃるかも知れません。まずはコードを触ってみて、慣れることから始めるとスムーズに理解が進むと思います。

Eメール購読

パンセのタネの記事まとめ、ニュース、トレンド情報をお届けします。

RECOMMEND

CATEGORY