Twitterで『Power Apps Communityのサンプルでレーダーチャートがある』という呟きを拝見したのがきっかけです。
ただしこちらのコンポーネント、8角形と5角形のみで値も5段階のみということでした。
よく見る3角形のレーダーチャートとか、10段階のチャートとかも使えないようでしたので、一般化してみました。
すぐできそうだったのでレーダーチャートの一般化にトライしている。 https://t.co/f9d1A93HPl pic.twitter.com/xKK02VzNKk
— Hiro (@mofumofu_dance) February 15, 2022
3以上のN角形で、M段階のレーダーチャートを作成できます。
もちろん値の表示も可能です。
ということで、今回はSVGのレーダーチャートをどうやって作ったかを紹介します。
サンプルのダウンロードは以下からどうぞ
SVG で多角形を描く
SVGで多角形を描くときには、<polygon ~/>
という要素を使います。polygonでは多角形の各頂点のXY座標を指定します。
四角形を描くときには4つのXYペアを指定します。
"data:image/svg+xml,"& EncodeUrl( "<svg viewBox='-110,-110,220,220' xmlns='http://www.w3.org/2000/svg'>" &"<polygon points='100,-100 -100,-100 -100,100 100,100' stroke-width='1' stroke='darkgray' fill='none'/>"//多角形はpolygon要素で頂点のXY座標を指定 &"</svg>" )
XYペアを任意の個数指定すれば、N角形を描くことができますね。
たいていの場合、Power Appsで特定の規則に従った数字の組 を作るときには Sequence()
関数を使うことでスッキリ書けます。(一般のN角形とかにもすぐ適用できる)
任意の多角形N を描くのであれば、Sequence()
とConcat()
関数を組み合わせて
Concat(Sequence(N),100*Cos(2*Pi()*Value/N)&","&100*Sin(2*Pi()*Value/N)," ")
これでN角形の各頂点座標を生成できます。例えば5角形であれば上の式にN=5を設定するとX,Yの組が5つ生成されます。
これを使って、polygonの座標を指定します。Power Apps上では以下のように書けます。
"data:image/svg+xml,"& EncodeUrl( "<svg viewBox='-110,-110,220,220' xmlns='http://www.w3.org/2000/svg'>" &"<polygon points='"&Concat(Sequence(N),100*Cos(2*Pi()*Value/N)&","&100*Sin(2*Pi()*Value/N)," ")&"' stroke-width='1' stroke='darkgray' fill='none'/>"//多角形はpolygon要素で頂点のXY座標を指定 &"</svg>" )
ここで、100*Cos(...
の 100は図形の大きさを表します。これを大きくしたり小さくすれば、大きい/小さい多角形も書くことができます。
複数の多角形を一緒に描く
レーダーチャートの目盛り部分は複数の大きさの正N角形を組み合わせてできています。例えば大きさ100の5角形と大きさ50の5角形を重ねて書きたい場合には
"data:image/svg+xml,"& EncodeUrl( "<svg viewBox='-110,-110,220,220' xmlns='http://www.w3.org/2000/svg'>" &"<polygon points='"&Concat(Sequence(N),100*Cos(2*Pi()*Value/N)&","&100*Sin(2*Pi()*Value/N)," ")&"' stroke-width='1' stroke='darkgray' fill='none'/>" &"<polygon points='"&Concat(Sequence(N),50*Cos(2*Pi()*Value/N)&","&50*Sin(2*Pi()*Value/N)," ")&"' stroke-width='1' stroke='darkgray' fill='none'/>" &"</svg>" )
polygonを2つ続けて書けばOKです。
では任意の段階に分割するにはどうすればいいかというと、またSequenceとConcatを使います。
100
の部分を100/M*value
みたいに、M分割すればいいわけです。
Concat( RenameColumns(Sequence(M),"Value","val"), "<polygon points='"&Concat(Sequence(N),100/M*val*Cos(2*Pi()*Value/N)&","&100/M*val*Sin(2*Pi()*Value/N)," ")&"' stroke-width='1' stroke='darkgray' fill='none'/>", Char(10) )
こんな感じで、連結していきます。
N=5, M=4のケースではpolygon要素が4つ生成されます。
SVGにすれば確かに4つの5角形が均等な幅で表示されます。
全体の回転
上の図を見てみると、なんとなく傾いています。実際、期待する正多角形 (真ん中上に頂点がくる) からすると90度傾いています。
この傾きを補正するために、SVG全体を-90度回転させます。
これには transform='rotate(-90)'
というおまじないをくっつけます。
こうするとSVG全体が-90度回転してくれます。
よく見る感じのレーダーチャートの基礎部分ができました。
あとは同じように、polygonを使ってデータを表示します。ここまででお気づきかもしれませんが 100
の部分をいい具合に置き換えてあげればいいわけです。
今回のコンポーネントでは[10,20,45,11,...]
のようなデータを収めた数値の配列を入力していただくと、いい具合に (Last(FirstN(....))
部分) レーダーチャートのデータを表す多角形を描いてくれています。
おわり
ということで、サンプルをただ使うだけでもいいんですが、大体どこで何をやっているかわかっていただけたらと思い、概要をご紹介しました。
一般化する!といったときに大体はSequence関数を、文字列を生成するにはConcatを使って勝負します。何かの一般化するときの発想の種になれば幸いです。
改めて、サンプルは以下からどうぞー。