- 締切済み
レーダーチャートの描画
正五角形でレーダーチャートをactionscript にて描画したいと思っています。 それぞれの頂点の値は、100がMAXのメモリ中、80,50,60,50,40となっています。 ご教授願います。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- DPE
- ベストアンサー率85% (666/776)
ムービークリップの中心点を中心とする円を想定し、これに内接する五角形と考えると分かりやすいです。 目盛りや文字は、正確にその割合の位置に配置してさえおけば、それほど大きくズレることはないと思います。 円の中心から内接する正五角形の各頂点に向かって直線を引くと、直線の長さは円の半径にあたります。 実際のチャートでは頂点が表現したい割合によって移動しますので、この直線の長さは半径×割合となります。 正五角形の各頂点から円の中心に線を引いていくと、正五角形は5つの三角形に分割できます。 できた三角形の、円の中心側の頂点に注目しますと、この角度は 360 ÷ 5 = 72 で 72 °です。 この角度と円の半径、それから表現したい割合を元にチャートの各頂点の座標を算出できます。 角度から位置を求めるには、三角関数の sin と cos を使います。 詳しくは書きませんが、 X = 半径×cosθ Y = 半径×sinθ で求められます。 今回は更に、半径に割合を乗算することで、チャートの頂点を算出できます。 求めた頂点が算出できれば、あとは順番に線でつないでいけば五角形のチャートになります。 配列変数に入れておくと、ループで処理できるのでスクリプトがスッキリまとまります。 ------------------------------------------------------- 「挿入」→「新規シンボル」で空のムービークリップシンボルを1つ用意し、このインスタンスをステージに配置します。 絵がないので、ステージでは○に+が重なったマークとして表示されますが、これは正常です。分かりにくいようでしたら、シンボルの+マークの位置を中心に、チャートに外接する円と同じ大きさの円を仮に描画しておくといいでしょう。 仮に、表示したい値が _root 階層(メインのタイムラインのフレーム)にある ratio0 ~ ratio4 という変数に割合(0.0 ~ 1.0 )で入っているとします。 実際は数値をパーセントで持っているようなら、予め 100 で割って対応してください。 先ほど作った空っぽのムービークリップシンボルのインスタンスをステージに配置し、これに次のようなスクリプトを設定します。 次の作例ではとりあえず、enterFrame イベントを利用して ratio0 ~ 4 の値を常に監視し、チャートがリアルタイムで変化するようにしています。 (↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください。このまま使うとシンタックスエラーになります) onClipEvent(load) { //五角形チャートの各頂点座標を保持する配列変数 vertex = new Array(); //五角形チャートに外接する円の半径 r = 100; //表示データを保持する変数のターゲットパス path = _root; } onClipEvent(enterFrame) { //各データから頂点の座標を求める //チャートの中心はムービークリップの中心点 for( i = 0 ; i < 5 ; i++ ) { //各頂点のラジアンを求める radian = 72 * i * Math.PI / 180; //外接円の中心から各頂点までの距離を求める //距離は割合に応じて変動 dist = r * path[ "ratio" + i ]; //角度と中心からの距離を元に頂点の座標を算出し、配列変数に格納 ver_x = dist * Math.cos( radian ); ver_y = dist * Math.sin( radian ); vertex[ i ] = { x : ver_x , y : ver_y }; } /*チャートの描画*/ //線のスタイルと描画開始位置を設定 this.clear(); this.lineStyle( 1 , 0x000000 , 100 ); this.moveTo( vertex[ 0 ].x , vertex[ 0 ].y ); //各頂点を線で結ぶ for( i = 1 ; i <= 4 ; i++ ) { this.lineTo( vertex[ i ].x , vertex[ i ].y ); } //最後の頂点と最初の頂点を結ぶ this.lineTo( vertex[ 0 ].x , vertex[ 0 ].y ); } メインのタイムラインのフレーム1に ratio0 = 1; ratio1 = 1; ratio2 = 1; ratio3 = 1; ratio4 = 1; というスクリプトを書いて、「ムービープレビュー」で動作を確認してみてください。 正常に動作していれば、ムービークリップの中心点を中心とする正五角形が描画されます。 正五角形が無事に表示されましたら、次は、上記の数値を 0.0 ~ 1.0 の間の数値に適当に変更してみてください。チャートの頂点が指定の割合に応じて移動します。 また、半径を保持する変数 r の値を変えると、チャートの大きさを変えることができます。 Flash の座標は数学で扱う座標軸とは違い、Y軸は画面下方向が正なので、時計で言うところの3時の方向を0°とし、時計回りに角度が決まります。 上記の例ですと、チャートの頂点は3時の方向が ratio0 、以降は頂点を時計回りに見て ratio1 →2→3→4と対応します。データを対応させる頂点にはご注意ください。 データを格納している変数の名前が不規則な場合や、頂点の順番とデータの位置が上手く合わない(例えば反時計回りの頂点に ratio0 ~ 4 と対応させたい場合など)は、配列変数を利用して合わせると簡単です。 チャートの向きがご希望に合わない時は、ラジアンを求める計算の時に //各頂点のラジアンを求める radian = ( 72 * i + 54 ) * Math.PI / 180; このように補正値を加えてください。 ざっと試したところ、54°くらいの補正で正五角形が傾くことなく表示されるようです。 ちなみに、ムービークリップの _rotation プロパティを利用してムービークリップ全体を回転させるのも、1つの手ではあると思います。
五角形でグラフの場合, 目盛りや文字なども入るため,100がMAXの線と,そのグラフ全体の大きさとの比が出ません。 だから,中心座標を自動的に取得して,その中で線を結ばせると言うのが不可能ではないかと思われるので,一部手動の作成方法です。 _root に graph というインスタンス名のムービークリップがあり, その中に五角形のグラフが書かれていたとします。 五角形のグラフの上にレイヤーを1つ作り,そこに,point1~point5 というインスタンス名のムービークリップを配置します。場所は適当でかまいません。 これはポイント用のムービークリップで,直径2~5pxくらいの小さな丸が良いと思います。 また,_root に val_1~val_6 という変数名のテキスト入力のテキストフィールドを用意し, val_1には80,val_2には50,… と書いて行っておきます。 そして,_root にボタンを作って, 以下のようなスクリプトを書けば,ボタンをクリックしたときに,point1~5がグラフ上に並び, そのpoint1~5が赤い線で結ばれるものになります。 必要なものをまとめて書いておくと, テキストフィールド 変数val_1~val_6 ボタン ムービークリップ graph └ムービークリップ point1~point5 のような感じです。 以下ボタンに書くスクリプトです。 ----------------------------- on (release) { //ココは調節してください(※1↓) xpos = 115; //ココも調節してください ypos = 120; //ココも調節してください(※2↓) rate = 1.2; _root.graph.point1._x = xpos+val_1*Math.cos(90*Math.PI/180)*rate; _root.graph.point1._y = ypos-val_1*Math.sin(90*Math.PI/180)*rate; _root.graph.point2._x = xpos+val_2*Math.cos(18*Math.PI/180)*rate; _root.graph.point2._y = ypos-val_2*Math.sin(18*Math.PI/180)*rate; _root.graph.point3._x = xpos+val_3*Math.cos(306*Math.PI/180)*rate; _root.graph.point3._y = ypos-val_3*Math.sin(306*Math.PI/180)*rate; _root.graph.point4._x = xpos+val_4*Math.cos(234*Math.PI/180)*rate; _root.graph.point4._y = ypos-val_4*Math.sin(234*Math.PI/180)*rate; _root.graph.point5._x = xpos+val_5*Math.cos(162*Math.PI/180)*rate; _root.graph.point5._y = ypos-val_5*Math.sin(162*Math.PI/180)*rate; //線の太さと色を設定してください(太さ, 色)です。 _root.graph.lineStyle(1, 0xFF0000); _root.graph.moveTo(_root.graph.point1._x, _root.graph.point1._y); _root.graph.lineTo(_root.graph.point2._x, _root.graph.point2._y); _root.graph.lineTo(_root.graph.point3._x, _root.graph.point3._y); _root.graph.lineTo(_root.graph.point4._x, _root.graph.point4._y); _root.graph.lineTo(_root.graph.point5._x, _root.graph.point5._y); _root.graph.lineTo(_root.graph.point1._x, _root.graph.point1._y); } ----------------------------- ※1 xpos = 115; ypos = 120; でグラフの中心座標が決まります。 val_1に0を書いて,クリックしたときの位置が,五角形の中心に来るように調節してください。 ※2 rate = 1.2; でグラフの大きさが決まります。 val_1に100を書いて,クリックしたときの位置が,五角形の目盛り100の位置と合うように調節してください。 ここの※1※2の部分が,冒頭で「一部手動の作成方法です。」と書いた手作業の部分です。 本当は,sin とか cos はラジアン単位です。 ラジアンで直接行く方がシンプルなのかもしれませんが,度で行っています。 数学が苦手なのです。 また図を使えば個々になぜそうなるのか説明出来ますが, テキストだけのため,各行の詳細説明は省略させていただきました。