〽️「こうしたい」ときのホームです。
「「3//Js読み込み」」 <script defer src = "https://fuuno.net/fuuno_code/fuuno_circle_graph.js"></script>
「「3<!--HTMLコード-->」」
<div class = 「「5"circle_graph_area"」」
data-donuts = "「「20〜100で指定」」"
data-stroke = "「「2onで隙間」」"
data-backcircle = "「「2offで背景円を非表示」」">
<sector data-color = "「「2色」」">
<sector data-color = "「「2色」」">
</div>
こんにちは、「ふ」です。
今回はSVGの円グラフを自動作成する、というものを作ってみました。
<div class = "circle_graph_area">
<div data-rate = "40"></div>
<div data-rate = "20"></div>
<div data-rate = "10"></div>
</div>
Javascriptを読み込んでおいて、⬆︎のようにHTMLコードを指定すると....
コーディングする方であれば、作成ツールを使うよりも手軽に円グラフが作成できます。 生成されたものは単なる<div>要素なので、レイアウトも自由に行えます。またSVGを使っているため、サイズを問わず「くっきり表示」が可能です。
またHTMLタグに属性を追加することで、デザインをカスタマイズできるようにもしました。
「ふ」も自分で作っておきながら、とても重宝しています。
みなさんも、ぜひぜひ使ってみてください🎵
はじめに、JavaScriptを読み込んでください。
HTMLファイルの<header>などの場所に、次の記述をします。
<script defer src = "https://fuuno.net/fuuno_code/fuuno_circle_graph.js"></script>
外部読み込みをしたくない方やscriptに手を加えたい方は、以下のコードをHTMLファイルに流し込んで下さい。
//グラフエリアを取得
const graph_areas = document.querySelectorAll(".circle_graph_area");
//各グラフエリアに対しての処理。
graph_areas.forEach(function(value) {
//縦横比をスタイリング
value.style.aspectRatio = "1/1";
//areaのindexを文字列として取り出す
const area_num = String(Array.from(graph_areas).indexOf(value));
//svg_areaの生成
let svg_area = document.createElementNS("http://www.w3.org/2000/svg","svg");
svg_area.setAttribute("viewBox","0 0 100 100");
//graph_areaに追加
value.appendChild(svg_area);
//maskされるグループを生成
let masked = document.createElementNS("http://www.w3.org/2000/svg","g")
//idを付与。あとでこのidを取得してmaskする。
masked.setAttribute("id",`masked${area_num}`);
//親SVGに追加
svg_area.appendChild(masked);
//backcircleがoffでなければ、背景に円を配置
if(value.dataset.backcircle != "off") {
let backcircle = document.createElementNS("http://www.w3.org/2000/svg","circle");
backcircle.setAttribute("cx","50");
backcircle.setAttribute("cy","50");
backcircle.setAttribute("r","40");
backcircle.setAttribute("fill","#ddd");
//stroke属性がonなら
if(value.dataset.stroke == "on") {
backcircle.setAttribute("stroke","#fff");
}
//マスクされるグループ「.masked」に追加
masked.appendChild(backcircle);
}
//扇作成。中心の座標と初期角度0を設定。
let prex = 50;
let prey = 10;
let sumdegree = 0;
//consoleに表示するグラフの項目
console.log(
`
グラフ${parseInt(area_num)+1}-color
`);
//扇形を作成
for (i = 0; i<value.children.length-1; i++) {
//入力された%値から角度を算出。
let degree = 360*parseFloat(value.children[i].dataset.rate)/100;
let color = value.children[i].dataset.color;
//自動配色。
let wari = 360/value.children.length;
let tasi = 360-wari;
let def_hue = (wari+tasi*i)%360;
//具体的な色指定がなければ自動配色を適用。
if(!value.children[i].dataset.color) {
color = `hsl(${def_hue},50%,69%)`;
}
//consoleに表示する。
console.log(`${i+1}:${color}`);
//degreeが180以上か否かで、第4引数の値を分岐。
let dai4;
if(degree <= 180) {
dai4 = 0;
} else {
dai4 = 1;
}
//要素の合計が100%を越えたら、警告。
if((degree+sumdegree)>360) {
alert(`${parseInt(area_num)+1}つ目のグラフ、内容の合計が100%を越えています。`)
}
//扇形外周部のxy座標
let afx = Math.sin((degree+sumdegree)*Math.PI/180)*40+50;
let afy = 50-Math.cos((degree+sumdegree)*Math.PI/180)*40;
//パスを作成
let oug = document.createElementNS("http://www.w3.org/2000/svg","path");
//塗りとパスデータ
oug.setAttribute("fill",color);
oug.setAttribute("d",`M50,50 L${prex},${prey} A40,40 0 ${dai4} 1 ${afx},${afy}Z`);
//stroke属性がonなら
if(value.dataset.stroke == "on") {
oug.setAttribute("stroke","#fff");
}
//親要素に追加
masked.appendChild(oug);
//角度の累積を更新
sumdegree += degree;
//扇形の円周部の座標を更新
prex = afx;
prey = afy;
}
//ドーナツ用のmaskを作成
//ドーナツ属性があれば
if(value.dataset.donuts) {
let graph_mask = document.createElementNS("http://www.w3.org/2000/svg","mask");
graph_mask.setAttribute("id",`mask${area_num}`)
//内部の白長方形
let sirorect = document.createElementNS("http://www.w3.org/2000/svg","rect");
sirorect.setAttribute("width","100%");
sirorect.setAttribute("height","100%");
sirorect.setAttribute("fill","#fff");
graph_mask.appendChild(sirorect);
//くり抜く黒丸
let kuromaru = document.createElementNS("http://www.w3.org/2000/svg","circle");
//donutsの指定は100未満にする。
if(parseInt(value.dataset.donuts)>=100) {
alert(`${parseInt(area_num)+1}つ目のグラフ、🍩の指定は100未満で行ってください。`)
}
kuromaru.setAttribute("cx","50");
kuromaru.setAttribute("cy","50");
kuromaru.setAttribute("r",`${parseInt(value.dataset.donuts)*0.4}`);
graph_mask.appendChild(kuromaru);
svg_area.appendChild(graph_mask);
//マスクをかける
document.getElementById(`masked${area_num}`).style.mask = `url(#mask${area_num})`
}
});
<div class = "「「1circle_graph_area」」"> </div>
円グラフを配置したい場所に<div>領域を設け、class名を「circle_graph_area」とします。すると....
ベースとなる円が描画されました。
子要素に内容となる「sector(扇形)」を追加していきます。
例えば、20%のものを配置したい場合、
<div class = "circle_graph_area">
<sector 「「1data-rate = "20"」」></sector>
</div>
sector要素にdata-set属性を記述、値を「20」とします。これはHTMLのdata属性を利用したものです。
値は文字列にする必要があるため、クオテーションで囲むようにしてください。
20%のsector(扇形)が描画されました。
さらにsectorを追加していきましょう。
<div class = "circle_graph_area">
<sector data-rate = "20"></sector>
<sector data-rate = "15"></sector>
<sector data-rate = "10"></sector>
</div>
順次描画されていきます。
現在sectorのカラーは指定がないため、自動配色となっています。具体的にはhslで彩度と輝度を固定し、色相だけをテキトーに変化させています。
〜基本の書き方は以上ですが、円グラフをカスタマイズできるよう、次のようなdata属性を用意しました。
・data-color →sectorの色
・data-donuts →中央を空洞にする場合、その割合
・stroke →sectorに白の縁取り線を付けます。
・backcircle →下地となる円の表示/非表示。
このあと、1つづつ紹介していきます。
sectorの塗りつぶし色は、個別に指定することができます。
<div class = "circle_graph_area">
<sector
data-rate = "20"
「「1data-color = "rgb(0,0,255)"」」></sector>
<sector
data-rate = "15"
「「1data-color = "orange"」」></sector>
</div>
子要素にdata-color属性を作り、色を指定して下さい。
値の形式は、CSSで使えるものならなんでもOKです。
1つ目のsectorがblue、次のものがorange になりました。
<div class = "circle_graph_area">
<sector
data-rate = "20"
data-color = "rgb(0,0,255)"></sector>
<sector
data-rate = "15"
data-color = "orange"></sector>
「「3<!--color指定なし-->」」
<sector
data-rate = "15"></sector>
</div>
先ほどのサンプルのように、指定しない場合はそのsectorだけが自動配色となります。

指定した色や自動配色の結果は、JavaScriptコンソールに表示されます。
<span style = "color:rgb(0,0,255)">■</span> : 20% <span style = "color:orange">■</span> : 20% <span style = "color:hsl(0,50%,69%)">■</span> : 20%
■ : 20%
■ : 15%
■ : 15%
⬆︎グラフの内訳表示などに利用してください。
〜以降紹介するものは、親のcircle_graph_areaに指定できる属性です。
data-donuts属性は、円グラフの中央に空洞を作ります。指定のない場合は「空洞なし」となります。
先ほどの円グラフに空洞を空けてみましょう。
<div class = "circle_graph_area"
「「1data-donuts = "50"」」>
〜略〜
</div>
値は0〜100%の範囲で、「%」を付けずに数値のみを記述してください。
50%の空洞付きグラフが描画されました。
data-stroke属性をONにすると、個々のsectorに白い縁取り線が付きます。
<div class = "circle_graph_area"
data-donuts = "50"
「「1data-stroke = "on"」」>
〜略〜
</div>
sector1つ1つに縁取りされたため、見た目上sector間にわずかな間隔ができています。
デフォルトでは背景にベースとなる円が配置されますが、非表示にすることもできます。data-backcircleを定義し、値を"off"としてください。
<div class = "circle_graph_area"
data-stroke = "on"
「「1data-backcircle = "off"」」>
<sector
data-rate = "20"
data-color = "rgb(0,0,255)"></sector>
<sector
data-rate = "15"
data-color = "orange"></sector>
<sector
data-rate = "25"></sector>
</div>
背景の円が消えました。
最後までお読みくださり、ありがとうございました。
ネット上には、グラフ作成ツールはたくさん存在します。しかしながら、簡単なグラフを作るために1回1回アクセスし、できたものをダウンロードしてくる....というのも面倒なものです。
これはもしかして、「コーディングをする人であれば、HTMLだけでサクッと作れたほうが断然楽チンなのでは?」と思い、今回の「SVG円グラフシステム」作成に及んだ次第です。
カスタマイズ機能については「差し当たりこういうのが必要かな?」と思ったものを何個か用意しました。もしみなさんのほうで「こんなカスタマイズ機能がほしい」ということであれば、ぜひリクエストしてみてください。実装できそうなものがあれば、アップデートさせていこうと思っています。
ではまた〜 ♪
ベクターグラフィック、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。