〽️「こうしたい」ときのホームです。
「「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、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。