CSSで円グラフを作るシンプルな仕組みを知ろう【グラフ数値の変更ができない場合】

CSSで円グラフを作るシンプルな仕組みを知ろう【グラフ数値の変更ができない場合】

CSSで円グラフを作るシンプルな仕組みを知ろう【グラフ数値の変更ができない場合】

cssの円グラフはbefore疑似要素を半円グラデーション付きの親要素の上に重ねる事でできています。

50%までは回転させてズレた分を利用し、51%以降はズレに加えてbefore疑似要素自体の色を変えてパーセンテージに使います。

svgの円グラフはstrokeの間隔を円周程度までに広げてstrokeの幅でパーセンテージを表現します。開始位置は-90度する必要があります。

昔は円グラフの実現は難しかった

円グラフは単純な統計から進行状況など非常に一般的な情報ですし、資料にデータ表示させる時は必須の表現ですよね。

ただちょっと前までは、WEBサイト上で円グラフを作成・表示するのは簡単ではありませんでした。

それまでの円グラフの実装方法

・画像ソフトを使用して円グラフの複数の値を表示した画像を作成する
・グラフ用に設計されたJavaScriptフレームワークで表示する

など、いずれかの方法でしたね。

なので一昔前のWEBサイトでは、円グラフを表示しているサイト自体が少なかった気がします。

今は実現が非常に簡単・サンプルも多数あり

しかし今はCSS3の登場により、簡単に複数のデータ円グラフを表示させる事ができる様になっています。

簡単に使いまわせるWEBサイト上のデザインサンプルがたくさん出回っている位です。

ただそれを丸ごとコピペするだけだと、数値やグラフを変える時に応用が効かない使い手になってしまいます。

本記事では、CSSの円グラフがどのような仕組みで実現されているかに注目をして紹介したいと思います。

円グラフの基本的な仕組み

今回のサンプルは非常に単純なマークアップの構成を元に説明します。

1つの要素のみで構成し、残りは疑似要素と変換・CSSグラデーションなどで行われます。

まずはシンプルな20%を表示する円グラフを作りましょう。

基本の要素づくり

<div class="pie"></div>

まず要素を円として装飾する必要があります。これが円グラフの背景になります。

.pie { width: 100px; height: 100px; border-radius: 50%; background: #1abc9c; }

css円グラフ構成図1

0%または100%を示した円グラフとも言えますね。

円グラフは緑色で、パーセンテージを示す色をオレンジにしたいと思います。

50%の2色グラデーション

パーセンテージの部分を表現するために、円の左側と右側の部分を2色で着色します。

その上で緑色の擬似要素を回転させて、必要なパーセンテージのみを両要素の「ズレ」で表示する事になります。

円の右側をオレンジに着色するためにCSSグラデーションを使用します。

.pie { width: 100px; height: 100px; border-radius: 50%; background: #1abc9c; background-image: linear-gradient(to right, transparent 50%, #fe8a01 0); }

css円グラフ構成図2

単純な線形のグラデーションで、円の右側半分をオレンジに着色した例です。

図2は50%の円グラフとしてはこれで十分ですよね。まあそれでは使えない訳ですが。

before疑似要素で見えない長方形を重ねる

次にマスクとして機能するbefore疑似要素のスタイルを設定します。

.pie::before { content: ''; display: block; margin-left: 50%; height: 100%; }

css円グラフ構成図3

マスクとして機能させる疑似要素を赤枠で示しています(50%透過しています)。

図3を見るとわかるように「疑似要素」が親要素の上に重なって配置されています。

上記はあえて背景色を50%透過で設定しているので、長方形の存在がわかりますよね。

疑似要素を半円にしつつ色を同じにする

疑似要素を右半円にする

長方形のままでは使えないので、長方形を半円にする必要があります。

スタイルで「overflow: hidden」を適用するか「border-radius」を使用します。

疑似要素の色を同じにする

今は赤く見えていますが、本来はサークル円のオレンジ部分を緑で覆うため親要素と同じ緑にしなければなりません。

緑色の背景を適用するのですが、この時グラデーションまで踏襲しないように「background-color: inherit」を使用します。

回転時は疑似要素の左中心が軸

円の中心部分(疑似要素の左中心)を軸として回転させるため「transform-origin: left;」を適用します。

この「transform-origin: left;」が無いと「疑似要素の中心」が回転軸になるので、グラフがずれてしまいます。

まとめると疑似要素のCSSは次のようになります。

.pie { width: 100px; height: 100px; border-radius: 50%; background: #1abc9c; background-image: linear-gradient(to right, transparent 50%, #fe8a01 0); } .pie::before { content: ''; display: block; margin-left: 50%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background-color: inherit; transform-origin: left; }

css円グラフ構成図4

スタイリングが完了した後の疑似要素(ここではあえて赤したままmarginを30%にずらしています)。

上記のコードを使うと赤色やズレはできません。

background: inherit;を使わない様に

CSSソースでは「background-color: inherit;」としています。

-colorを省いて「background: inherit;」としないように注意してください。

ここを「background: inherit;」にしてしまうとグラデーションも継承されてしまいます。

疑似要素を回転させて下地を見せる

次からいよいよ疑似要素の左側中央を中心に(円の中心ですね)回転させます。

transform:rotate()プロパティを適用することにより、疑似要素を回転させる事ができます。

回転角度の計算方法

20%の割合を指定するには

・「72deg」(0.2×360 = 72)transform: rotate(72deg);
または
・「.2turn」transform: rotate(.2turn);

css円グラフ構成図5(数値ごとのパターン)

それぞれの値を変更してどのように見えるかをいくつかご紹介します。

10%

36degまたは.1turn

20%

72degまたは.2turn

40%

144degまたは.4turn

このように様々なパーセンテージを示す円グラフになります。

ここまでは0~50%まで(右半分)の場合のみ

ここまでで大体理解できた事でしょうが、もう少し続きがあります。

この円グラフは0~50%まで(右半分)のパーセンテージを表示するための手順です。

ここで「.6turn」を適用して60%の回転を描こうとすると、図6の様になります。

css円グラフ構成図6(正常でない円グラフ)

パーセンテージが50%を超えると、円グラフのパーセンテージの開始位置自体がずれるのです。

60%以上の場合は、設定を修正する必要があります。

60%以上の円グラフの表現方法

50%~100%のパーセンテージは0%~50%とは設定が変わります。

before疑似要素を緑色にしていましたがこれをオレンジに変えるのです。その上で要素を10%回転させます。

したがって60%の円グラフの場合の疑似要素のコードは次のようになります。

.pie{ width: 100px; height: 100px; border-radius: 50%; background: #1abc9c; background-image: linear-gradient(to right, transparent 50%, #fe8a01 0); } .pie::before{ content: ''; display: block; margin-left: 50%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background-color: inherit; transform-origin: left; background: #fe8a01; /*ここで色をオレンジにする*/ transform: rotate(.1turn); }

css円グラフ構成図7(正しい60%の円グラフ)

10%(.1turn分)だけ回転させると下地のオレンジが10%見えますよね。

あえて上記はbefore疑似要素を赤くしていますが、本来は右半円背景と同じオレンジにします。

このようにして合計60%分を実現するのですね。

右半円と左半円の表現の仕方

0~50%まで

・疑似要素を緑色にして回転させた時に見せる下地の度合いで表現

50~100%まで

・疑似要素をオレンジにして、回転させて見せた下地+疑似要素のオレンジの合計で表現

という仕組みです。

これでパーセンテージを表現する方法が完成しましたね。

アニメーション効果の付いた円グラフ

これにCSSアニメーションを使用すれば、進行状況インジケーターを作成することもできます。

css円グラフ構成図8(アニメーション円グラフ)

円グラフがうまくいかない場合のポイント

これまで説明したシンプルな円グラフを作るポイントは以下の通りです。

円グラフを作るポイント

・1.円グラフのベースとなる円を半々でグラデーションしているか?
・2.before:疑似要素は、margin-left: 50%を入れて親要素に重ねているか?
・3.疑似要素を半円にするためborder-radiusを設定しているか?
・4.背景の色を踏襲するのはbackground-color: inheritであり、backgroundを使っていないか?
・5.円の中心から回転させるため、transform-origin: left;で傾けているか?
・6.%の割合は360度×%でdeg数値で表すか、10%単位であれば.1turn。数値を間違っていないか?
・7.50%以上の場合、before要素をパーセンテージ色にしているか?
・8.60%なら10%(.1turn)70%なら20%(.2turn)という感じで50%を引いた残りを回転させる事に注意

50%以上の設定例

例:78%の場合

50%を引いた28%(360×28%=101deg)だけ回転させれば、50%+28%の回転で表現できる

SVGによる円グラフの基本的な仕組み

SVGは多くのグラフィカルタスクを容易ににする要素です。円グラフも例外ではありません。

少し複雑な計算を必要とするパスを使って、円グラフを作成する事になります。

SVGの基本形を構成

まずは前回同様にサークルから始めましょう。そして基本的なスタイルを適用します。

<svg width="100" height="100"><circle r="30" cx="50" cy="50"></svg>
circle { fill: #1abc9c; stroke: #fe8a01; stroke-width: 30; }

構築された円が図1となります。

svg円グラフ構成図1

半径rは30で太いオレンジのストロークがある緑のSVG円になりました。

破線のストロークを構成

ストロークは、strokeプロパティとstroke-widthプロパティだけではなく、微調整ができる様々なプロパティがあります。

今回は「破線のストローク」を作成するために「stroke-dasharray」を使います。

破線のストロークを使う事で、ストロークの間隔をあける事ができます。

circle { fill: #1abc9c; stroke: #fe8a01; stroke-width: 30; stroke-dasharray: 20 10; }

svg円グラフ構成図2

上記がstroke-dasharrayで作成された破線のストロークです。ストロークの間隔が空いていますよね。

長さ(ダッシュ)が「20」、間隔(ギャップ)が「10」が反映されています。

ストロークを調整する

ここまで、一見SVGストロークと円グラフと無関係のように思うかもしれません。

では次にストロークを調整(幅と間隔の変更)するとどのようになるのかを見てみましょう。

ストロークの間隔と円周

ストロークの間隔調整は、は円の外周(円周)と関係してきます。

※「円周」は2πrの公式に当てはめると、今回の円の円周は「2π×半径rが30のcircle=およそ189」になります。

それを目安にストロークの間隔が決定されます。

円周189における間隔調整

circle.cr1, circle.cr2, circle.cr3, circle.cr4 { fill: #1abc9c; stroke: #fe8a01; stroke-width: 30; stroke-dasharray: 0 189; } circle.cr2 { stroke-dasharray: 40 189; } circle.cr3 { stroke-dasharray: 95 189; } circle.cr4 { stroke-dasharray: 150 189; }

svg円グラフ構成図3

複数のstroke-dasharray値とそのストローク効果

「0 189」
「40 189」
「95 189」
「150 189」

それぞれ3時の方向を開始地点として189の円周のうち、それぞれの数値分ストロークを表示しています。

それぞれのストロークについて

指定した円周のパーセンテージの様なストローク状態になるのです。

「全体189のうち40・95・150だけストロークを出す」という様な感じでしょうか。

円の半径によってストローク数値が変わる

円の半径が変われば円周が変わるので、ストロークの数値「189」も変わります。

うまくパーセンテージが出せないのはここに原因がある可能性が多いです。

円グラフに近づける

次に円の半径を十分に小さくしてストロークで完全に覆われると、円グラフに非常によく似たものになります。

たとえば次のコードで生成されるように半径が25で「stroke-width」が50の円にすると、図4のようになります。

<svg width="100" height="100"><circle r="25" cx="50" cy="50"></svg>
circle { fill: #1abc9c; stroke: #fe8a01; stroke-width: 50; stroke-dasharray: 60 158; }

svg円グラフ構成図4

半径rが25に対しstroke幅を2倍の50で設定すると、緑の円の中心までストロークが届きます。

これを円グラフに利用しているのです(開始位置は必ず3時の方向からになります)。

SVGグラフィックが円グラフに近くなってきましたよね。

ただ、まだストロークが長すぎてはみ出している様な状態になっています。

円グラフへの仕上げ

最後にストロークの下に大きな緑色の円を追加します。

HTML要素でもある<svg>要素にborder-radiusで50%のスタイルを設定して円を広げます。

かならず3時から始まる事に注意

同時にデフォルトで3時の方向から始まるストロークを、90度左回転(マイナス数値)させておきます。

どんな円グラフも大体は12時の方向からデータが始まるはずです。

ですのでcssのtransform: rotate(-90deg); はどんな場合も変更する必要は無いと言えますね。

最終的な結果を図4に示します。

svg { transform: rotate(-90deg); background: #1abc9c; border-radius: 50%; }

svg円グラフ構成図5(最終的なSVG円グラフ)

これでSVG画像による円グラフを作る事ができましたね。

SVG円グラフが上手くいかない場合のポイント

SVGによる簡単な円グラフを作るポイントは以下の通りです。

SVG円を作るポイント

・1.円グラフのパーセンテージ部分(オレンジ部分)はstrokeで作っているか?
・2.strokeは円の枠の中心から設定px分だけ内外に発生する(円の外周・内周からではない)
・3.円の半径(r)の数値の2倍のstroke幅を付けて完全に円を覆いつくしているか?
・4.パーセンテージ部分はstroke-dasharrayを使って間隔を空けているか?
・5.stroke-dasharrayを設定する時、対象とする円の円周を計算しているか?
・6.円周は2πrで表すので、半径の大きさによって変わる
・7.半径rが30なら2×3.14×30=188.4(189)、半径rが50なら2×3.14×50=314
・8.stroke-dasharrayの間隔は必ず3時の方向からスタートする
・9.[3]の円を覆いつくしつつ、stroke-dasharrayの間隔でパーセンテージ部分を表現しているか?
・10.ベースのsvg要素のborderをradiusで50%に設定すれば、stroke-dasharrayのはみ出た部分を覆いつくせる
・11.12時の方向からパーセンテージを始めるため、3時から始まるstrokeを-90度回転させているか?

半径の2倍のstroke幅を付ける場合

円の半径の2倍の数値のstroke幅を付けた場合、大きくなり過ぎて円になり切れない場合があります。

その場合はsvgのサイズおよび、その中心軸位置(cx・cyの数値)を広げて下さい。

stroke-dasharrayの間隔を「円周」とした場合

stroke-dasharray: 40 189;などのように、右にある数値が円周の数値になります。

そうすれば必ずstrokeの長さ「40」の開始位置は3時の方向からになります。

最後に円のborderをradiusで50%にする理由

グラフにする為に円の半径の2倍のstroke幅を付けています。

stroke幅の半分(50%分)は円の内側に入ってきています。

円のborder幅を50%アップ(色は同じ色)にすれば、50%外にはみ出たstrokeに追いつくという事になります。

3色の円グラフ事例

3色の円グラフも、conic-gradientのグラデーション機能を使えば簡単に実現できます。

注意:サポートしていないブラウザがある

conic-gradientプロパティは2018年9月からGoogle Chormeでサポートされるようになりました。

今はスマホ版Safariでも反映されるので、iPhoneではきちんと表示されるようになっています。

EdgeやFirefoxではまだ未反映の様ですね。

3色円グラフcssコード

.pie { width: 100px; height: 100px; border-radius: 50%; background: conic-gradient(deeppink 20%, #fb3 0, #fb3 30%, #1abc9c 0); }

3色円グラフ構成図

まとめ

今回はシンプルで1つのパーセンテージのみを表示させる仕組みを詳しく解説させて頂きました。

円を3つ4つに分割するグラフもデザインサンプルがたくさん出ていますが、基本は上記の形となります。

自在に数値を変更するためには必須で把握をしておかなければならない基本の仕組みですので、しっかりマスターして欲しいと思います。

円グラフが上手くできない場合は、本記事に上げた項目・ポイントに気を付けてチェックをしてみてください。

この記事をシェアする

一押し人気コーナー紹介

CSS関連記事