ノードの線をクリックされたら指定のURLへ飛ばすようにGraphaGearを拡張する方法
GraphGear の拡張ネタです。今日はノードの線をクリックされたときに,ノードごとに別の URL へ移動するようにします。以前,
■GraphGear の Node と Node 間に引かれる線にクリックイベントを追加するhttp://d.hatena.ne.jp/masutaro/searchdiary?word=%2a%5bFlash%5d
というエントリを書きましたが,今日のエントリは前回のからもう一歩踏み込んだ拡張になります。エントリの内容は,前回からの続きで書いてあるので前回を読んでいない方は前回のものから読まれることをお勧めします。
まず,ノードの関係を記述している XML ファイル(デフォルトではsimple.xml)を以下のように拡張します。
<?xml version="1.0"?> <graph title="My graph title" bgcolor="0xffffff" linecolor="0xcccccc"> <node id="n1" text="Creative Synthesis" color="0x6000ff" textcolor="0xffffff"/> <node id="n2" text="Recycle Research" color="0x0060ff" textcolor="0xffffff"/> <node id="n3" text="Graph Gear" color="0x0060ff" textcolor="0xffffff"/> <node id="n4" text="Personal Zeitgeist" color="0xff0060" textcolor="0xffffff"/> <node id="n5" text="Recycle Canvas" color="0x00ff60" textcolor="0xffffff"/> <node id="n6" text="Researc Art Science" color="0xff6000" textcolor="0xffffff"/> <node id="n7" text="Design Graph" color="0x60ff00" textcolor="0xffffff"/> <edge sourceNode="n1" targetNode="n2" label="" textcolor="0x555555" link="http://www.amazon.co.jp/○○○○"/> <edge sourceNode="n1" targetNode="n3" label="" textcolor="0x555555" link="http://www.amazon.co.jp/○○○○"/> <edge sourceNode="n1" targetNode="n4" label="" textcolor="0x555555" link="http://www.amazon.co.jp/○○○○"/> <edge sourceNode="n1" targetNode="n5" label="" textcolor="0x555555" link="http://www.amazon.co.jp/○○○○"/> <edge sourceNode="n2" targetNode="n6" label="" textcolor="0x555555" link="http://www.amazon.co.jp/○○○○"/> <edge sourceNode="n2" targetNode="n7" label="" textcolor="0x555555" link="http://www.amazon.co.jp/○○○○"/> </graph>
次に,tempEdge の拡張を行います。僕の手元にあるソースは自分で読むようにコメントを入れているので,正確ではありませんが58行目くらいからの部分でしょうか。以下のようなソースがあると思います。コメントを書いてある部分が修正する箇所です。
if(graphsource.firstChild.childNodes[i].nodeName == "edge") { var sourceNode = graphsource.firstChild.childNodes[i].attributes.sourceNode; var targetNode = graphsource.firstChild.childNodes[i].attributes.targetNode; var sourceRef = eval("_root.Graph.GraphFrame.Node" + sourceNode); var targetRef = eval("_root.Graph.GraphFrame.Node" + targetNode); sourceRef.connectedList.push(targetRef); targetRef.connectedList.push(sourceRef); var tempEdge = _root.Graph.GraphFrame.attachMovie("edgeDebug", "Edge" + sourceNode + targetNode, _root.Graph.GraphFrame.getNextHighestDepth()); tempEdge.content.text = graphsource.firstChild.childNodes[i].attributes.label; tempEdge.content.textColor = graphsource.firstChild.childNodes[i].attributes.textcolor; /* 修正箇所 */ /* tempEdge 自身にリンク先のURLを持たせる */ tempEdge.link = graphsource.firstChild.childNodes[i].attributes.link; if(tempEdge.content.text) { tempEdge.onRelease = function() { getURL(this.link, '_blank'); } } /* 修正箇所ここまで */ eList.push(new Edge(sourceRef, targetRef, tempEdge)); }
以上の修正をソースファイルに加えてパブリッシュすると,ノードの線をクリックしたときにノードごとのリンク先が開くようになります。
■ワンポイント
各ノードごとにリンクを設定しているのに,線をクリックすると全部同じ URL へ移動してしまうという質問があったので,なぜそういうことが起こってしまうのか簡単にですが説明します。
tempEdge.onRelease = function() { getURL(this.link, '_blank'); }
これは,tempEdge の onRelease イベントを定義している部分です。Flash には特有のクセがあって,このとき onRelease に代入された無名関数 function() { 〜 } には,スクリプトを記述したタイムライン のスコープが適用されます。なので,例えば上のコードの this.link を link に書き換えると・・
tempEdge.onRelease = function() { getURL(link, '_blank'); }
link は まずタイムライン上の link を見に行き,なければ graphsource.onLoad = function() { 〜 } の中の link を見に行く,という動きをします。試しにこのコードでパブリッシュして実行してみると link の値は undefined になりました。 タイムライン上にも,graphsource.onLoad = function() { 〜 } の中でも, var link が定義されていないからです。onLoad = function() { 〜 } の書き方をするときはスコープに注意しなくてはなりません。
上に書いた拡張ソースでは,まず tempEdge 自身にリンク先のURLを持たせるようにして・・
tempEdge.link = graphsource.firstChild.childNodes[i].attributes.link;
getURL の中では this.link と明示的に this を指定して tempEdge の link を見るようにしました。
tempEdge.onRelease = function() {
getURL(this.link, '_blank');
}
どうでしょうか?説明が下手で上手く伝わるように書けているか不安ですが,以下のサイトにより詳しい解説が載っています。もっと詳しく知りたい方はこちらをお読みください。
参考サイト:FumioNonaka.com
http://www.fumiononaka.com/TechNotes/Flash/FN0601002.html
http://www.fumiononaka.com/TechNotes/Flash/FN0303004.html
http://www.fumiononaka.com/TechNotes/Flash/FN0303004.html#DefaultReference