コピペで簡単!CSSとjQueryで作る「積み上げ棒グラフ」の実装方法

Webサイトで統計データや数値を分かりやすく伝えたい時、「グラフ」は非常に強力なツールです。特に、内訳を同時に見せられる「積み上げ棒グラフ」は多くの場面で役立ちます。

しかし、グラフの実装は少し難しそう…と感じるWebサイト運営初心者の方もいらっしゃるかもしれません。そこで今回は、HTML、CSS (SCSS)、そしてjQueryを使って、アニメーション付きの積み上げ棒グラフを実装する方法をご紹介します。

まずは完成デモをご覧ください。各棒が下から上へ伸びるアニメーションが確認できるかと思います。

HTMLの構造

まず、グラフの骨格となるHTMLです。.graph_area という大枠の中に、Y軸の目盛り(.graph-y)、グラフ本体(.inner_graph)、X軸の項目(.graph-x)を配置しています。

積み上げグラフのキモは、.bar(棒1本)の中に、積み上げる要素(.typeA-1, .typeB-1)を入れている点です。

HTML

<div class="graph_area">
   <h3 class="graph_caption">グラフのタイトル</h3>
   <p class="unit">[kWh]</p>
   <ul class="graph-y">
     <li><span>300</span></li>
     <li><span>250</span></li>
     <li><span>200</span></li>
     <li><span>150</span></li>
     <li><span>100</span></li>
     <li><span>50</span></li>
     <li><span>0</span></li>
     <li id="js-inner_graph" class="inner_graph">
       <div id="bar1" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar2" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar3" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar4" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar5" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar6" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar7" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar8" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar9" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar10" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar11" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
       <div id="bar12" class="bar">
         <div class="typeA-1"></div>
         <div class="typeB-1"></div>
       </div>
     </li>
   </ul>
   <table id="js-graph-x" class="graph-x">
     <tr>
       <td>1月</td>
       <td>2月</td>
       <td>3月</td>
       <td>4月</td>
       <td>5月</td>
       <td>6月</td>
       <td>7月</td>
  _      <td>8月</td>
       <td>9月</td>
       <td>10月</td>
       <td>11月</td>
       <td>12月</td>
     </tr>
   </table>
 </div>

SCSSでのスタイリング

次に、スタイルをSCSSで記述します。SCSSを使うことで、グラフの幅($gw)や高さ($gy)を変数として管理でき、メンテナンス性が向上します。

ポイントは以下の通りです。

  • Y軸(.graph-y): li 要素の ::after 疑似要素を使って目盛りの横線を描画しています。
  • グラフ本体(.inner_graph): display: flex;align-items: flex-end; を指定し、棒グラフが下端(Y軸の0)から伸びるように配置しています。
  • 積み上げ(.bar): .bar 自体も display: flex;align-items: flex-end; を使い、中の要素(.typeA-1, .typeB-1)が下から積み上がるようにしています。

SCSS

$gw:370; //グラフの幅
$gy:250; //グラフの高さ
$yw:(70/370*$gw)*1px;		//Y軸の幅
$xw:((370-70)/370*$gw)*1px;	//X軸の幅
$barw:(10*2+2/370*$gw)*1px;	//barの幅
$yh:(200/200*$gy)*1px;	//Y軸の高さ
$unith:($gy/6)*1px;	//単位の高さ

* { box-sizing: border-box; }

.graph_area {
  margin: 2em;
  width: #{$gw}px;
  font-size:small;
}
.graph_caption {
  text-align: center;
}
.unit { 
  margin-bottom: 1em; 
  width: $yw;
  text-align: right;
}
.graph-y {
  padding: 0 0 1em;
  position: relative;
  height: $yh;
  li {
    display: flex;
    align-items: flex-start; 
    justify-content: space-between; 
    height: $unith;
    span {
      padding-right: .5em;
      display: block;
      position: relative; top: -.5em;
      width: $yw;
      text-align: right;
    }
    &:after { //線
      display: block;
      width: $xw; height: 2px;
      background: #d5d5d5;
      content: "";
    }
  }
  .inner_graph {
    margin: 0;
    display: flex;
    align-items: flex-end;
    justify-content: space-around;
    position: absolute;
    bottom: 0; right: 0;
    width: $xw; height: $yh;
    &:after { content: none; } //線なし
    .bar {
      display: flex;
      flex-direction: row;
      align-items: flex-end;
      justify-content: space-around; 
      height: $yh;
    }
    .typeA-1,.typeB-1 {
      width: ($barw - 4)/2;
    }
    .typeA-1 {
      background-color: blue;
    }
    .typeB-1 {
      background-color: orange;
    }  
  }
}
.graph-x {
  margin-left: auto;
  display: flex;
  justify-content: space-around;
  width: $xw; text-align: center;
}

jQueryでのアニメーション

最後に、グラフにデータを反映し、アニメーションさせるためのjQuery(JavaScript)です。

data_A_monthdata_B_month という配列に、積み上げたい2種類のデータ(この例では12ヶ月分)を格納します。

barHeight 関数が、これらの配列データを受け取り、Y軸の最大値(ここでは300)に対する割合(%)を計算して、.animate() メソッドで各要素の高さを変更しています。アニメーションの速度は 500(ミリ秒)に設定されています。

jQuery

	var barHeight = function (arName, idName) {
		for (var i = 0; i <= arName.length; i++) {
			var barH = (arName[i] / 300) * 100 + "%";
			$("#bar" + (i + 1) + " ." + idName).animate({ height: barH }, 500);
		}
	};
  data_A_month = [244,233,12,44,123,45,11,77,65,123,12,300]
  data_B_month = [290,213,52,94,13,5,111,57,75,153,32,59]
	barHeight(data_A_month, "typeA-1");
	barHeight(data_B_month, "typeB-1");

まとめ

今回は、HTML、SCSS、jQueryを使った積み上げ棒グラフの実装方法をご紹介しました。JavaScriptの配列データを変更するだけで、グラフが動的に変わるため、CMSやデータベースと連携させる際にも応用しやすい構造です。

ぜひこのコードをベースにして、あなたのWebサイトのデータ視覚化に役立ててください。


よくある質問(FAQ)

Q1: グラフのデータ(数値)はどこで変更すればよいですか?

A1: jQueryコード内の data_A_month = [...]data_B_month = [...] の配列部分です。この [...] の中の数値を変更することで、グラフの各棒の高さが自動的に変わります。Y軸の最大値(目盛り)を変更する場合は、jQueryコード内の (arName[i] / 300)300 という数値と、HTMLのY軸の目盛りを併せて修正してください。

Q2: SCSSではなく、通常のCSSで使いたい場合はどうすればよいですか?

A2: SCSSコードをCSSにコンパイル(変換)する必要があります。上記のデモ(jsfiddle)の「CSS」タブに表示されているコードがコンパイル後のCSSですので、そちらをコピーしてご利用ください。SCSSの変数($gw など)が固定値に置き換わっています。

Q3: jQueryを使わずに、CSSだけでアニメーションはできませんか?

A3: はい、可能です。CSSの animation プロパティや transition プロパティを使うことで、グラフの高さをアニメーションさせることができます。ただし、JavaScriptで設定しているデータ(data_A_month など)の値に応じて動的に高さを変えるには、結局JavaScript(プレーンなJavaScriptまたはライブラリ)でインラインスタイル(例:style="height: 50%;")を書き換える処理が必要になることが多いです。

CONTACT

webサイト制作、デザインに関するご相談、御見積のご依頼など、弊社へのお問い合わせはこちら