カテゴリー
CSS HTML jQuery Webサイト作成

円チャートの描画

こんにちは、エムケーワイです。ゆる~~くjQueryの勉強を進めています(体調不良になったりして、あまり進んでません^_^;)。

今回は、スマホのメモリ管理アプリでメモリを解放する際等に表示される円チャートでの進捗表示を実現してみました(インフォグラフィックっていうやつ?)。

まずは、結果からです。下の”DRAW”ボタンを押してみてください。

0 %

では、実現方法を説明して行きます。今回も”overflow: hidden”の応用です。

目次 [閉じる]
  1. HTMLコード
  2. CSS設定
  3. jQueryコード

1. HTMLコード

円チャートに関する部分のHTMLコードは下記の通りです。カスタムHTMLで作成しました。

<div class="mkyBackground">
    <button class="mkyJsDraw">Draw</button>
    <div class="mkyProgressC">
        <div class="mkyProgressCMask1 left">
            <div class="mkyProgressCMask2">
                <div class="mkyCircle"></div>
            </div>
        </div>
        <div class="mkyProgressCMask1 right">
            <div class="mkyProgressCMask2">
                <div class="mkyCircle"></div>
            </div>
        </div>
        <div class="mkyProgressCContent">
            <p class="mkyProgressCText">
                <span class="mkyProgressCTextV">0</span>
                <span class="mkyProgressCTextM">%</span>
            </p>
        </div>
    </div>
</div>
  • <div class=”mkyBackground”>は、ボタンと円チャートを含むブロックです。
  • まず”DRAW”ボタンを設置しています。
  • <div class=”mkyProgressC”>が円チャートになります。進捗に従って円周を描画するためのコンテンツは、クラス”mkyProgressCMask1″を持つ2つのdiv要素で実現されています。
  • クラス”mkyProgressCMask1″を持つdiv要素は、内部にクラス”mkyProgressCMask2″を持つdiv要素と、クラス”mkyCircle”を持つdiv要素を有します。
  • “mkyCircle”は描画される円周と同色の円です。
  • “mkyProgressCMask1″と”mkyProgressCMask2″は、幅が”mkyCircle”の直径の半分で、高さが”mkyCircle”の直径と同じである矩形で、”mkyCircle”上に左右に並べて配置されます。
  • “mkyProgressCMask1″と”mkyProgressCMask2″は、CSSで“overflow: hidden”が設定され、初期状態では”mkyCircle”が完全に隠されます。“mkyCircle”に対するマスクの役割を果たします。
  • 円周を描画する際は、”mkyCircle”の中心を軸に”mkyProgressCMask2″を回転させます。すると、“mkyProgressCMask1″と”mkyProgressCMask2″が重なった部分のみ”mkyCircle”が表示されます。これにより進捗に従って円周が描画されるように見せることができます。
  • 上記の方法では、最大で”mkyCircle”の半分しか表示できないので、同じ構成をもう一つ用意して同じ位置に配置し、”right”で”mkyCircle”の右側部分を、”left”で”mkyCircle”の左側部分を表示します。
  • <div class=”mkyProgressCContent”>は、進捗のテキスト表示を行う部分です。初期値は”0%”です。全体のブロックは”border-radius: 50%”で円形となっとり、これが”mkyCircle”上に表示されるので、進捗に従って外側に円周が描画されるように見えます。

円の左右に”overflow: hidden”の2枚の矩形マスクを配置し、円の中心を軸に一方のマスクを回転させると、2枚のマスクが重なった部分のみ円が表示される…

“overflow: hidden”はこんな応用もできるんですね!

2. CSS設定

CSS設定についてパーツごとに説明します。

2-1. 背景

.mkyBackground { 
    height: 40rem;
    background-color: #303030;
}
  • 高さと背景色を設定しています。

2-2. ボタン

button.mkyJsDraw {
    position: relative;
    margin: 0 auto;
    display: block;
    top: 2rem;
    width: 13rem;
    border-radius: 20px;
}
button.mkyJsDraw:disabled {
    background-color: gainsboro;
    cursor: wait;
}
  • 表示位置、幅、角の丸め量を設定しています。
  • チャート描画中(jQueryにより”disabled”が設定される)の背景色、カーソル形状を設定しています。

2-3. 円チャート全体

.mkyProgressC { 
    position: relative; 
    margin: 2rem auto;
    top: 2rem;
    width: 26rem;
    height: 26rem;
}
  • 表示位置、幅、高さを設定しています。

2-4. マスク

.mkyProgressCMask1,
.mkyProgressCMask2 {
    overflow: hidden;
    position: absolute;
    width: 13rem;
    height: 26rem;
}
.mkyProgressCMask1.left {
    left: 0;
}
.mkyProgressCMask1.right {
    right: 0;
}
.mkyProgressCMask1.left .mkyProgressCMask2 {
    left: 100%;
    -webkit-transform-origin: 0 50%;
    transform-origin: 0 50%;
}
.mkyProgressCMask1.right .mkyProgressCMask2 {
    right: 100%;
    -webkit-transform-origin: 100% 50%;
    transform-origin: 100% 50%;
}
  • “overflow: hidden”、”position: absolute”を設定しています。
  • マスクの幅を親要素(“.mkyProgressC”)の半分、高さを親要素と同じに設定しています。
  • 左側の”mkyProgressCMask1″を親要素の左半分に配置しています。
  • 右側の”mkyProgressCMask1″を親要素の右半分に配置しています。
  • 左側の”mkyProgressCMask2″を親要素(“mkyProgressCMask1.left”)の右隣に配置し、回転の中心を自身の左辺中心に設定しています。
  • 右側の”mkyProgressCMask2″を親要素(“mkyProgressCMask1.right”)の左隣に配置し、回転の中心を自身の右辺中心に設定しています。

2-5. 円

.mkyCircle {
    position: absolute;
    width: 26rem;
    height: 26rem;
    background-color: darkorange;
    border-radius: 50%;
}
.mkyProgressCMask1.left .mkyCircle {
    right: 0;
}
.mkyProgressCMask1.right .mkyCircle {
    left: 0;
}
  • “border-radius: 50%”で円にしています。
  • 幅と高さを”.mkyProgressC”と同じにしています(幅がマスクの2倍)。
  • 位置は絶対指定ですが、直接の親要素が”.mkyProgressCMask2″であるため、”.mkyProgressCMask1.left”側には”right: 0″を、”.mkyProgressCMask1.right”側には”left: 0″を設定することになります。

2-6. テキスト表示

.mkyProgressCContent {
    position: absolute;
    left: 2rem;
    top: 2rem;
    width: 22rem;
    height: 22rem;
    background-color: #fff;
    border-radius: 50%;
    padding-top: 8.5rem;
    text-align: center;
    -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
}
.mkyProgressCContent .mkyProgressCText { 
    margin: 0;
    line-height: 1;
}
.mkyProgressCContent .mkyProgressCTextV {
    font-size: 50px;
    font-weight: bold;
}
.mkyProgressCContent .mkyProgressCTextM {
    font-size: 30px;
}

<全体ブロックに対する設定>

  • 幅と高さを”.mkyProgressC”より4rem(40px)小さくしていますが、中心は”.mkyProgressC”と一致するよう位置を調整しています。
  • 背景色を白とし、”border-radius: 50%”で円にしています。
  • “padding-top”でテキストの上下方向の位置を調整しています。
  • テキストの左右方向の位置を中心にしています。
  • 周囲に影をつけています。

<テキストに対する設定>

  • 数値部分が大きなフォントで強調表示されるよう設定しています。

3. jQueryコード

今回作成したjQueryコードは下記の通りです。

jQuery(function () {

    var _drawButton = jQuery('.mkyJsDraw');
	
    _drawButton.on('click', function() {
        var _charts = jQuery('.mkyBackground').find('.mkyProgressC');

	// ボタンのアンフォーカス、無効化
	_drawButton.blur();
	_drawButton.prop('disabled', true);
		
        // 円チャートを描画(とりあえず複数対応)
        _charts.each(function() {
            var _chart = jQuery(this),
                // Mask2の回転角度を0に戻す
                _circleLeft = _chart.find('.left .mkyProgressCMask2')
                    .css({ transform: 'rotate(0)' }),
                _circleRight = _chart.find('.right .mkyProgressCMask2')
                    .css({ transform: 'rotate(0)' }),
                // パーセント値表示を0に戻す
                _percent = _chart.find('.mkyProgressCTextV').text(0);

            // 進捗描画処理
            jQuery({ percent: 0 }).delay(1000).animate({ percent: 100 }, {
                duration: 2000, 
                progress: function() {
                    var currentP = this.percent,
                        deg = currentP * 360 / 100,
                        degR = Math.min(Math.max(deg, 0), 180),
                        degL  = Math.min(Math.max(deg - 180, 0), 180);
                    _circleRight.css({ transform: 'rotate(' + degR + 'deg)' });
                    _circleLeft.css({ transform: 'rotate(' + degL + 'deg)' });
                    _percent.text(Math.floor(currentP));
                },
                complete: function() {
                    // ボタンの有効化
                    _drawButton.text('Redraw');
                    _drawButton.prop('disabled', false);
                }
            });
        });
    });
});
  1. 円チャート上部のボタンをクリックすることで描画が始まります。
  2. _chartsに”.mkyBackground”内のクラス”.mkyProgressC”を持つオブジェクトを取得・代入します。
  3. ボタンをアンフォーカス、無効化し、円チャート描画中はクリックできないようにします。
  4. _chartsの各オブジェクトに対して円チャートの描画処理を行います。今回は”.mkyProgressC”を持つオブジェクトは1つしかありませんが、複数ある場合にも対応できるようeach()を使用しています。
  5. 変数に必要なオブジェクトを取得・代入するとともに、初期状態として”.mkyProgressCMask2″の回転角度を0度、テキスト表示を0%にしています。このような記述をすれば、オブジェクトの取得と同時にCSS設定や文字列の設定ができるのですね!
  6. 次にアニメーションの記述です。今回は”.mkyProgressCMask2″を回転させていくのですが、animate()では数値ではない”rotate()”を操作することはできないという事なので、パーセント値を操作するようにします。パーセント値は0%から100%まで変化します。“jQuery({ percent: 0 }).animate()”のように記述することで、セレクタ指定で取得したオブジェクトのプロパティ以外を操作してアニメーションを実現することができるのですね!
  7. アニメーションは”delay(1000)”により、ボタンクリックの1秒後に開始します。
  8. アニメーションの所要時間は2秒です(“duration: 2000”)。
  9. progressオプションでアニメーションの各ステップで実行される処理を定義しています。この中では、現在のパーセント値を角度に変換し、左右の”.mkyProgressCMask2″の回転角度を設定しています。パーセント値が50%(180度)までは右側の”.mkyProgressCMask2″が回転し、50%を超えると左側の”.mkyProgressCMask2″が回転が回転することになります。併せてテキスト表示も変更しています。
  10. completeオプションでアニメーション完了時に実行される処理を定義しています。この中でボタンを有効化しています。また、1度円チャートを描画すると、ボタンのテキストが”REDRAW”に変わります。

いかがでしたでしょうか?

今回は進捗表示という事で0%から100%まで変化させましたが、最終値を変えればいろいろなパーセント値に対応させることが可能です。

“overflow: hidden”っていろいろ応用できるのですね。これからも調べていってみようと思います。

最後までお読みいただきありがとうございました。

梅雨真っ只中、暑さや湿気で体調を崩しやすい今日この頃、皆様ご自愛くださいませ。