SVGで円グラフアニメーション。

〽️stroke-dashoffset。 〽️円周を100とする工夫。 〽️コーディング。 〽️自動化させたいですね。





⬆︎SVGついてのまとめページ、CSSアニメーションの基本コーナーはこちら。

こんにちは、「ふ」です。
前回の棒グラフに続き、今回はSVGで円グラフのアニメーションを作っていきましょう。

円グラフが扇状に広がっていく動きは、stroke-dasharrayとstroke-dashoffset。2つの「破線」に関するプロパティを利用します。

stroke-dashoffset。


CSSのstroke-dasharrayは「破線」の間隔を指定するプロパティです。
ではstoke-dashoffsetとは?どのようなプロパティなのでしょうか。

幅が100の直線、classを「sample」とします。
CSSで破線を施します。



■ CSS

.sample { stroke-dasharray:20; }

幅20ごとに「破線」と「隙間」が割り当てられました。
破線の開始位置は元の直線の始点と同じところから始まっています。ここにstoke-dashoffsetを指定してみます。

.sample { stroke-dasharray:20; 「「1stroke-dashoffset:10;」」 }


破線の開始位置が、元の直線の始点よりも後ろにずれました。
stroke-dashoffsetは、破線の開始位置を本来の基準からずらす、その量を指定します。正の値を指定すると、線分の開始位置はそのぶんだけ後退します。


今度は円で考えてみましょう。円周の長さを「100」とします。
画像はテキトーな幅で破線を施したところ。ここで、

stroke-dasharray:100;


もしdasharray(破線の長さ)が円周と同じ「100」であれば、1つの破線が円を1周します。
更にここにdashoffsetを指定します。

stroke-dashoffset:25;


破線の開始位置が「25」後退したため、最初の破線の到達点は全円周の75%の位置となりました。
このようにstroke-dashoffsetの値を調整することで、「破線の到達点」をコントロールすることができます。


またoffsetを円周と同じ「100」としたとき、円のストロークはdasharrayで指定した100の長さの「隙間」で覆い尽くされます。つまり、何も見えない状態。


これら2つの状態、

 offset:100 ▶︎ offset:任意

へとアニメーションさせれば、「動く円グラフ」の1部品が完成です。


線の幅はstroke-widthプロパティを使って、お好みで指定しましょう。
線幅を直径と同じにすれば、完全に円の内側が埋まります。

円周を100とする工夫。


  赤:40%
  青:35%
  黄:25%

この⬆︎ようなデータがあったとします。
円グラフに落とし込むとき。

「「3<!--円要素-->」」 <circle cx = "・・" cy = "・・" 「「4r = "5"」」 />

SVGのcircleは半径を指定するのですが、
例えば「 r = "5" 」とした場合、円周の長さは31.41592・・となります。


offsetは円周の長さに対して指定します。
グラフのデータは%単位。これを31.41592・・に割り付けるのはめんどくさすぎる。


円周の長さがちょうど「100」であれば、データの「%」からの落とし込みも非常にスムーズ。

「円周 = 100」としてそこから半径を求め、その値を使って<circle>要素を描きたい。
ただしSVGにおける円周率を示すpiのようなメソッドは見当たらないので、小数を使って算出します。そのとき、円周率はどこまでの精度で計算させればいいのでしょうか?

⬇︎。

「ふ」が検証した結果、"3.1416"と小数点4桁まで指定してやると、大きく拡大しても遜色ない正円を描画できることがわかりました。ここから半径を逆算します。
円周を100とした時の半径の大きさは、

100/3.1416/2 ≒ 15.9154

と出ました。この値を使って円を作っていきましょう。

コーディング。


  赤:40%
  青:35%
  黄:25%

先ほどのデータをそのまま使って、円グラフアニメーションをコーディングしていきましょう。


先づはSVG領域を確保します。
座標指定ですが、算出した半径「15.9154」の2倍(直径)以上、尚且つ太くしたstroke-widthの部分も納まるようにしましょう。x,yともに直径の2倍( ≒ 64 )としておけば間違いありません。

■ HTML

<svg class = "pi-graph" viewBox = "0 0 64 64"> </svg>

svgタグにはサイズなど調整できるよう、class名:pi-graphとしています。



ここに「 赤:40%」を配置してみましょう。破線の到達点が円周でいうところの「40」になれば良いので、stroke-dashoffsetは100-40の「60」ということに成増。

■ HTML

<svg class = "pi-graph" viewBox = "0 0 64 64"> 「「1<circle id = "red" cx = "50%" cy = "50%" r = "15.9154"/>」」 </svg>

円要素はid名:redとし、CSSを使って整形します。

■ CSS

#red { fill:none; stroke:#e90800; stroke-width:14; stroke-dasharray:100; 「「1stroke-dashoffset:60;」」 }

ん?!

グラフは上から始めたいのに、円の右部分から始まってしまっています。


原因。コードでcircleを描画したときに、パスの始点が右側になってしまっているんですね。
ここは<svg>要素ごと-90°回転させてしまいましょう。先程付けておいたclass名:pi_garaphで参照します。

■ CSS

.pi_graph { transform-origin:center; transform:rotate(-90deg); }


グラフの始点を上にすることができました。

次は「 青:35%」を赤の背面に重ねます。値は35%なので円弧の長さ自体は「35」なのですが、赤の40%の後に続く円弧でなくてはなりません。
したがって到達点は40+35の「75」、なのでオフセットは100-75の「25」と成増。

■ HTML

<svg class = "pi-graph" viewBox = "0 0 64 64"> 「「1<circle id = "blue" cx = "50%" cy = "50%" r = "15.9154"/>」」 <circle id = "red" cx = "50%" cy = "50%" r = "15.9154"/> </svg>

■ CSS

#blue { fill:none; stroke:#00a0e9; stroke-width:14; stroke-dasharray:100; 「「1stroke-dashoffset:25;」」 }


赤の背面に到達点「75」の青が追加されました。

最後、「 黄:25%」を最背面に配置します。
これに関しては到達点:100の位置なので、dashoffsetは初期値の「0」のままで大丈夫です。

■ HTML

<svg class = "pi-graph" viewBox = "0 0 64 64"> 「「1<circle id = "yellow" cx = "50%" cy = "50%" r = "15.9154"/>」」 <circle id = "blue" cx = "50%" cy = "50%" r = "15.9154"/> <circle id = "red" cx = "50%" cy = "50%" r = "15.9154"/> </svg>

■ CSS

#yellow { fill:none; stroke:#d6e900; stroke-width:14; stroke-dasharray:100; }


これで「アニメーションの終了状態」が完成です。

ではCSSアニメーションを仕掛けていきます。全ての円弧のstroke-dashoffsetを100、つまり非表示の状態からスタートさせ、それぞれの到達点まで延ばしていきます。

以下⬇︎が完成コードです。

■ HTML

<svg class = "pi-graph" viewBox = "0 0 64 64"> <circle id = "yellow" class = 「「4"enko"」」 cx = "50%" cy = "50%" r = "15.9154"/> <circle id = "blue" class = 「「4"enko"」」 cx = "50%" cy = "50%" r = "15.9154"/> <circle id = "red" class = 「「4"enko"」」 cx = "50%" cy = "50%" r = "15.9154"/> </svg>

重複しているCSSをまとめたかったので、各円弧にはclass名:enkoを指定しました。

■ CSS

「「4.enko」」 { fill:none; stroke-width:14; stroke-dasharray:100; 「「3/* 最初は非表示状態 */」」 「「1stroke-dashoffset:100;」」 } 「「3/* きいろ */」」 #yellow { stroke:#d6e900; animation:yellow 2s ease-in-out infinite; } @keyframes yellow { bbto { 「「1stroke-dashoffset:0;」」 } 「「3/* あお */」」 #blue { stroke:#00a0e9; animation:blue 2s ease-in-out infinite; } @keyframes blue{ bbto { 「「1stroke-dashoffset:25;」」 } 「「3/* あか */」」 #red { stroke:#e90800; animation:red 2s ease-in-out infinite; } @keyframes red{ bbto { 「「1stroke-dashoffset:60;」」 }





これで完成です。パイナッポー!
お疲れ様でした。

自動化させたいですね。


最後までお読みくださり、ありがとうございました。
今回のSVGによる円グラフのアニメーション。下準備は大変でした💧が、円周の長さを「100」にとることで、コードは比較的単純なもので実装できました。

ただし、まだ実用的とは言い切れません。
webに複数のグラフを表示したいときや、落とし込むデータの項目が増えてきた場合。その都度stroke-dashoffsetの値を逆算するのはめんどくさい。自動化させたいものですね。
ということで次の目標ができました、「自動円グラフアニメーションの実装」。

完成したら、フーノページに記事を落としたいと思います。お楽しみに笑
ではまた〜 ♪



SVGアニメーション、 回転の中心を指定する。

2021.03.09
座標を取得して%変換。


SVG アニメーション、カメラのシャッターを再現。

2021.04.11
「アニメーションごと」重ねていく。


ページめくりアニメーション 作り方。

2021.02.02
画像を読み込むだけで実装。












「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。