CSSとJavaScriptで配列から動く棒グラフを作ってみる[ライブラリ未使用]

CSSとJavaScriptで配列から棒グラフを作るコードを作ってみました。
アニメーションでぬるっと生えてきます。
ライブラリは使用しません。

コードの利用は自己責任でお願いします。

サンプル

    JavaScript配列

    const graphData = [
        [
            { name: 'data1', max: 100 },
            { title: 'a', count: 80 },
            { title: 'B', count: 25 },
            { title: 'c', count: 60 },
            { title: 'd', count: 45 },
        ],
        [
            { name: 'data2', max: 300 },
            { title: 'a', count: 70 },
            { title: 'B', count: 30 },
            { title: 'c', count: 280 },
            { title: 'd', count: 150 },
        ],
    ]
    • 変数「graphData」にグラフとして表示する情報を入力。
    • 配列1段目:「name」はHTMLと紐づけるための自由な名前を設定。(下記参照)
      「max」はこのグラフの最大値に設定したい数字を入力。
    • 配列2段目以降:「title」にグラフの項目、「count」にグラフの数字を入力。

    HTML

    <ul class="js-graph" id="data1"></ul>
    • クラス「js-graph」を設定したul要素にグラフが表示される。
    • id属性にJavaScript配列で設定した「name」と同じ名前を設定。(上記参照)

    CSS

    .js-graph {
        margin: 0;
        padding: 0;
        width: 500px; /* 好きな数値を設定(*1) */
        height: 500px; /* 好きな数値を設定(*1) */
        display: flex;
        list-style: none;
        justify-content: space-between;
        border-top: solid 1px;
        border-bottom: solid 1px;
        position: relative;
        margin-bottom: 100px !important;
    }
    
    .js-graph *{
        margin: 0 !important;
        padding: 0 !important;
    }
    
    .js-graph::before {
        content: "";
        position: absolute;
        width: 100%;
        height: 50%;
        top: 0;
        left: 0;
        border-bottom: solid 1px;
    }
    
    .js-graph li {
        width: 100%;
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        align-items: center;
        position: relative;
    }
    
    .js-graph li div {
        background: #555555; /* グラフの色 */
        position: relative;
        height: 0;
        transition: 1.5s;
    }
    
    .js-graph li p {
        position: absolute;
        bottom: -50px;
    }
    
    .js-graph li span {
        position: absolute;
        top: -30px;
        left: 0;
        width: 100%;
        text-align: center;
    }
    1. 全体のサイズを設定。(%等も可能。)

    JavaScript

    graphData.forEach(i => {
        let graphFragment = new DocumentFragment();
        let firstFrag = true;
        let name, max;
        i.forEach(ii => {
            if (firstFrag === true) {
                name = ii.name;
                max = ii.max;
                firstFrag = false;
            } else {
                const li = document.createElement('li');
                const div = document.createElement('div');
                div.setAttribute('data-height', Math.round(ii.count / max * 100) + '%');
                div.style.width = '50%';
                div.className = 'bar';
                const span = document.createElement('span');
                span.textContent = ii.count;
                const p = document.createElement('p');
                p.textContent = ii.title;
                li.appendChild(div);
                div.appendChild(span);
                li.appendChild(p);
                graphFragment.appendChild(li);
            }
        })
        let graphEl = document.getElementById(name);
        if (graphEl) {
            graphEl.appendChild(graphFragment);
        }
    })

    各グラフのcountとmaxから縦幅比率をパーセントで計算します。
    結果は各「bar」要素に「data-height」属性として付与され、まだ表示はされません。

    後は、好きな方法で「bar」に付与された「data-height」属性を「style:height」属性に変更してください。
    ページ内の全てのグラフに対して属性変更を行うなら以下の様な感じです。

    let bar = document.querySelectorAll('.bar');
    
    window.onload = function () {
        bar.forEach(i => {
            const height = i.getAttribute('data-height');
            i.style.height = height;
            i.removeAttribute('data-height');
        });
    }

    このページでは以下の様に「IntersectionObserver」を利用し、画面に表示されたらグラフが描画される様にしてあります。

    let options = {
        rootMargin: '0px',
        threshold: .5
    }
    
    let callback = (entries, observer) => {
        entries.forEach(entry => {
            if (entry.intersectionRatio > .5 && entry.target.classList.contains('active') == false) {
                bar = entry.target.querySelectorAll('.bar')
                bar.forEach(i => {
                    const height = i.getAttribute('data-height');
                    i.style.height = height;
                    i.removeAttribute('data-height');
                });
                entry.target.classList.add('active');
            }
        });
    }
    
    let observer = new IntersectionObserver(callback, options);
    
    let target = document.querySelectorAll('.js-graph');
    
    target.forEach(e => {
        observer.observe(e);
    });

    まとめ

    以上で完成です。

    他にも要素を追加したグラフや、他のタイプのグラフなども作ってみたいですね。

    サンプル集

      [
          { name: 'data2', max: 300 },
          { title: 'a', count: 70 },
          { title: 'd', count: 150 },
          { title: 'c', count: 280 },
      ],

        [
            { name: 'data3', max: 100 },
            { title: 'a', count: 30 },
            { title: 'd', count: 70 },
            { title: 'c', count: 20 },
            { title: 'd', count: 95 },
            { title: 'e', count: 55 },
        ],

          [
              { name: 'data4', max: 10000 },
              { title: 'a', count: 6510 },
              { title: 'd', count: 3820 },
              { title: 'c', count: 1995 },
              { title: 'd', count: 9820 },
              { title: 'e', count: 7777 },
          ],
          タイトルとURLをコピーしました