« 2012年2月 | トップページ | 2012年4月 »

2012年3月

2012年3月30日 (金)

9-ラック、フルラック

FlatTable に9-ラックとフルラックの自動生成機能を追加しました。ボタン[ Tot ]をクリックするとメニューが現れます。ラック内の球の位置を配列に設定しておいて、それを使って球を移動するだけなので、特に難しいことは有りません。

9rack --------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月29日 (木)

矢印球の色加工(修正)

先の「矢印球の色加工」で矢印球は複合図形なので、

    arrow.setAttribute(・・・);        // (1)
一発では色付け出来ないと書きましたが、それは間違いでした。

矢印球の SVG コードは、

    <g id="arw">
        <要素 A のデータ />
        <要素 B のデータ />
        <要素 C のデータ />
    <g>
となっていますが、各要素のデータに "fill""stroke" が無い場合に (1) で設定した値が有効になることが分かりました。これで、一々、子要素を個別に色加工する必要は無くなりました。

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月28日 (水)

スタンバイと終点への移動

FlatTable に球をスタンバイ位置へ移動するルーチンと経路の終点へ移動するルーチンを実装しました。ボタン[ Ball ]をクリックするとメニューが出ます。

この2つは簡単です。スタンバイの方は、

  1. 経路が有れば、それを消去する
  2. 球をスタンバイ位置に移動する
でOK。終点への移動の方は、
  1. 矢印球の位置を基礎球にコピーする
  2. 経路を消去する
  3. 基礎球を新しい位置に移動する
でOKです。

球の移動に関しては、まだ幾つか実装待ちの機能が有りますが、それらは後回しにして、次はラックの作成を予定しています。

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月26日 (月)

直線、ジャンプ、線幅変更ルーチン

FlatTable に直線とジャンプの作図ルーチンを追加しました。さらに、経路の線幅の変更ルーチンも追加しました。

FlatTable でジャンプは単に経路を部分的に非表示にするだけの機能です。図のように描くことでジャンプを表現することが出来ます。
配置図

ジャンプ作図ルーチンは次のようになっています。

//ジャンプの作図
function jumpLine(){
    ・・・
    if (currentBall == baseBall){
        各ゴースト(および矢印球)に付随する区間を
        非表示にする
    } else {
        現行の球に付随する区間を非表示にする
    }
    必要があれば経路の描画
    ・・・
}

直線作図ルーチンもほぼ同じです。共通部分をまとめてコードを短縮すべきかも知れませんが、それは後で検討することにします。

線幅は stroke-width1(narrow) と 13(wide) の2種類有り、メニューの[ Line narrow/wide ]をクリックすることで線幅を切り替えます。線幅の情報は基礎球の属性 fWide に保持し、[ Line narrow/wide ]のクリックに対するイベント・ハンドラー内で、

    if (baseBall.fWide = !baseBall.fWide){
        ・・・
    }
が実行されて、線幅の情報が切り替わります。ここで面白いと思ったのは、このルーチンが実行されるまで基礎球 baseBall には fWide は定義されていないのに、「当然のごとく」処理が進むことです。定義されていないことが定義を導いています。いわゆるLLと呼ばれる言語はどれもそうだと思いますが、なんとおおらかなことでしょう。

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月25日 (日)

曲線の作図

FlatTable に曲線作図ルーチンを追加しました。メニュー・ボタン[ Ball ]をクリックすると[ Curve ]と[ Ctrl-Pnt on/off ]の追加されたメニューが表示されます。因みに FlatTable で扱う曲線は2次のベジェ曲線です。

メニューの[ Curve ]をクリックした時の処理の流れは

    curveLine() ⇒ curve() ⇒ makeCtrlP()
制御点の図 となっています。[ Curve ]をクリックすると、現行の球とその1つ前の球の間に「+」が出現します。この「+」は曲線の制御点で、これをドラッグして曲線の形状を調節します。制御点のドラッグは球のドラッグと同じルーチンを使用しています。

制御点「+」は生成時に一時的に台のセンタースポットに配置し、その直後に translate() で本来の位置に移動します。これは、生成時の位置が translate() の基準点(原点)になることへの対応です。

        制御点の配置

function makeCtrlP(){
    ・・・
    var ctrlP = document.createElementNS(svgns, "path");
    ctrlP.setAttribute("style",
        "fill:none;stroke:" + ballColor[i] + ";stroke-width:3");
    var startpX = centerX - 4;    // 4 は十字の長さ(の半分)
    var startpY = centerY;
    ctrlP.setAttribute("d",
        "m " + startpX + "," + startpY + " 8,0 m -4,-4 0,8");
    ctrlP.x = (ball.x + ball.prev.x)/2;
    ctrlP.y = (ball.y + ball.prev.y)/2;
    ctrlP.setAttribute("transform",
        "translate(" + ctrlP.x + "," + ctrlP.y + ")");
    ・・・
}

この制御点は必要に応じて表示/非表示の選択が出来ます。操作はメニューの[ Ctrl-Pnt on/off ]で行います。操作したい制御点「+」もしくは曲線が指定されている球をクリックして現行の球にした後でこのメニューをクリックすると「+」の表示/非表示が切り替わります。なお、現行の球が基礎球の時は、その球の経路全体に対して制御点の表示/非表示を切り替えます。

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月20日 (火)

ゴーストの再利用が出来ない

経路作成の時、一度作成した経路を一旦キャンセルして新たに作成し直すことが有ります。その際、既に生成していたゴーストをお蔵入りにしてしまうのはモッタイナイ気がして、再利用することを考えました。

removeChild() したゴーストを appendChild() する訳ですが、そのゴーストへのポインターを保持していないので、それを取得しなければなりません。普通、SVG 要素へのポインターの取得は document.getElementById() で行います。しかし、これはその要素が appendChild() されていなければ機能しませんが、再利用したいゴーストは今 removeChild() 状態なのでポインターの取得が出来ません。即ち、ゴーストを再利用するにはゴーストへのポインターを別途保持しておく必要が有るのです。

そもそも、ゴーストの再利用は、システムへの負荷(特にメモリ・フラグメンテーション)を防ぐのが目的です。FlatTable の予想される使用状況から判断して、ゴーストの無駄遣いは高々数十個と思われます。この僅かな無駄遣いを無くすために、廃棄したゴーストの管理にコストを掛けるのは気が進みません。最悪のケースだと無駄遣いに上限は無いので、それを考慮すれば多少のコストを掛けてでも再利用した方が良いのかも知れませんが、最悪のケースは考えないことにします。

// ゴーストを再利用しないコード
function makeGhost(ball){
    var baseBall = ball.baseBall;
    var n = ++(baseBall.nGhost);
    var id = baseBall.id + "g" + n;
    var ghost = baseBall.cloneNode(true);  // 新しいゴーストを生成
    ghost.setAttribute("id", id);
    ghost.setAttribute("opacity", 0.3);
    ghost.x = ball.x;
    ghost.y = ball.y;
    ghost.setAttribute("transform",
        "translate(" + ghost.x + "," + ghost.y + ")");

    ghost.baseBall = baseBall;
    ghost.prev = ball.prev;
    ball.prev = ghost;
    ghost.next = ball;
    ghost.prev.next = ghost;

    flattable.appendChild(ghost);
    addEvent(ghost, "click", ballClick);
    return ghost;
}

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

メニューの表示

FlatTable のほとんどの機能はメニューを介して実行します。このメニューを表示する度に新たに作成していては、システム(特にメモリ)に負担が掛かるのが心配です。そこで、初めの考えでは、起動直後にメニューを作っておいて、必要な時に表示して、要らなくなったら非表示にするという方式にするつもりでした。

そのためには、メニューのZ軸順序を操作して最前面に表示する必要が有ります。しかし、SVG でのZ軸順序の操作方法が分かりません。もしかしたら、SVG では、Z軸順序の操作は出来ないのかも知れません。

やむをえず、起動直後に作っておいたメニューを、すぐに削除しておき、必要な時に appendChild() し、使い終わったら removeChild() することにしました。こうすれば、メニューは最前面に表示されることになります。 removeChild() したメニューがガベージコレクションで持って行かれないか気になるところですが、問題が発生しないことを期待することにします。

現在、実装済みのメニューは、球に関する次の2つです。

  • ゴーストの表示/非表示
  • 経路、ゴーストの削除

「SVG+JavaScript 版 FlatTable の試作品」で表示される画面の[ Ball ]をクリックすると上記2つのメニューが表示されます。この2つは経路が作成された状態でなければ意味を成しません。動作の確認は、まず、経路を作成してから行ってください(操作方法は「経路の作図-?-」を参考にしてください)。

Path_2 上記メニューのうち「経路、ゴーストの削除」は次のような動作になります(添付図参照)。操作対象として指定された球を「現行の球」と呼びます。基礎球か矢印球が現行の球の時「経路、ゴーストの削除」を実行すると、その経路が削除され、基礎球だけが残ります。ゴーストが現行の球の時「経路、ゴーストの削除」を実行すると、そのゴーストだけが削除され、その前後の球が経路で繋がります。

さて、予定している機能はまだまだ有りますが、今回の2つだけで巷の配置図ソフトと同程度の能力を備えたと言っても良いでしょう。実際、現時点で次のような配置図の作成が可能です(ただしPCのみ)。
12320a

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月12日 (月)

スマフォ非対応?

私はスマートフォンを(そしてタブレットも)持っていないので知り合いに Android で FlatTable の移植試作版にアクセスしてもらいました。クリックの具合を確認したかったのです。しかし、クリックうんぬん以前に問題の有ることが分かりました。SVG 画像が表示されません。1週間ほど前にも別の知り合いに、そちらは iPhone でアクセスしてもらったことが有りました。その時も画像は表示されませんでした。インターネットで調べたところ、iPhone の場合、SVG 対応が iOS4.3 は中途半端でダメ、iOS5.0 はOKということでした。Android の方は、知り合いのスマートフォンは最新版ということなので、全滅と考えて良いでしょう。

つまり、スマートフォンでは、極めて高い確率で FlatTable が使えないということになります。

FlatTable を SVG+JavaScript に移植しようと考えたのは、現行 FlatTable のプラットフォームである Flash がジョブズによって駆逐されそうだったからです。Flash がマイナーになる前に SVG+JavaScript 版を作ろうと思ったわけです。

しかし、そのスマートフォンでは使えないとは何事か?! ジョブズは Flash を叩くだけ叩いて、代替が準備できてないじゃないか!

2012年3月10日 (土)

矢印球の色加工

矢印球の色をそれぞれの基礎球に合わせて加工するルーチンを追加しました。矢印球とは図の球のことです。
矢印球の説明図

この矢印球はA、B、Cの3つの要素から成る複合図形です。この矢印球を arrow と置くと、このような複合図形の場合、単純に

    arrow.setAttribute(・・・);
では色の加工は出来ません。色を加工するには、その構成要素を指定する必要が有ります。今まで、この構成要素へのアクセス方法が分からず、色の加工が出来ませんでした。SVG の仕様書に何か書いていないか探したのですが、そこには無く、やっと JavaScript 側に解を見つけることが出来ました。それは、
    childNodes[]    子要素リスト
です。この childNodes に構成要素(子要素)が配列になって入っていることが分かりました。

矢印球の色の加工ルーチンは次のようになります。

    矢印球の色の加工
    var i = baseBall.id.lastIndexOf("b");
    i = baseBall.id.slice(++i);
    arrow.childNodes[1].setAttribute("style",
        "fill:" + ballColor[i] +
        ";fill-opacity:0.2;stroke:" + ballColor[i] +
        ";stroke-width:0.5"
    );
    arrow.childNodes[3].setAttribute("style", "fill:" + ballColor[i]);
    arrow.childNodes[5].setAttribute("style", "fill:" + ballColor[i]);
ballColor[] は球の色から成る配列で、i は球の番号になっています。childNodes[] の1、3、5番の要素が図のA、B、Cに対応しています。

それにしても、Flash の時は、矢印球の色の加工は簡単だったのですが、SVG+JavaScript には苦労させられます。

--------

ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月 9日 (金)

予定している機能

球の移動と経路作図のルーチンが出来たので、これからは FlatTable の機能を実装して行きます。予定している機能は次の通りです。

○ 個々の球に関する機能
  • ゴーストの表示/非表示の切り替え
  • 経路の線種の切り替え
  • 経路を曲線にする
  • 経路が曲線の時の制御点の表示/非表示の切り替え
  • 経路を直線にする
  • ジャンプボール
  • 経路・ゴーストの削除
  • 球をスタンバイ位置に移す
  • 球を経路の終点へ移す
  • 球をセンタースポットへ移す
  • 球をヘッドスポットへ移す
  • 球をフットスポットへ移す
  • 球をクッションに接触させる
  • 経路をバンクショットにする
  • 球の色でコメントを作成する
  • 球の減速倍率を設定する
  • 経路を使って領域を表示する
○ 台やページに関する機能
  • 全ゴーストの表示/非表示の切り替え
  • 全経路・全ゴーストの削除
  • 全球をスタンバイ位置に移す
  • スタンバイ位置の球の表示/非表示の切り替え
  • 全球を終点へ移す
  • 9-ボールのラック
  • フルラック
  • ページを複製する
  • ページを生成する
  • ページを削除する
  • グリッド表示/非表示の切り替え
  • 台の向きを変える
  • ページコードを表示する
  • コメントを作成する
  • ヘルプ表示
○ 配置コードに関する機能
  • 配置コードをコピーする
  • 配置コードを生成する
  • 配置コードを配置図に反映する
  • 配置コードの表示/非表示の切り替え
○ ページの合成に関する機能
  • ページ合成/解除を指定する
○ アニメーションに関する機能
  • 単発アニメーションを実行する
  • 連続アニメーションを実行する
  • スキップする/しないを切り替える
  • パラメータを表示する
  • パラメータを配置コードへ追加する/しないを切り替える
ここに挙げたもの全てを実装できるか疑問です。特に、文字入力に関する機能は自信が有りません。Flash だと、TextField が文字入力を引き受けてくれたのですが、SVG+JavaScript で同等のことが出来るのか不明です。

2012年3月 7日 (水)

経路の作図 -4-

作成した経路は削除することが出来ます。経路の描き直しの場合は基礎球(*)をクリックした後、長クッションの木枠をクリックすると、それまでの経路が消えて新たな作図モードに入ります。また、書き直しではなく、経路を削除するだけの操作は、そのユーザーインターフェースをこれから実装しますが、削除のルーチンは既に出来ています。

(*): ゴーストや矢印球の元となっている球を基礎球と呼ぶことにします。

経路削除のコードは次の通りです。


function delPath(baseBall, flag){
    var ball = baseBall.next;
    var arrow = baseBall.arrow;
    for (; ball != arrow; ball = ball.next){
        flattable.removeChild(ball);
    }
    baseBall.nGhost = 0;
    if (flag){        // (1)
        flattable.removeChild(arrow);
        baseBall.arrow = null;
        flattable.removeChild(baseBall.path);        // (2)
        baseBall.path = null;
        baseBall.next = null;
    } else {        // (3)
        arrow.x = baseBall.x;
        arrow.y = baseBall.y;
        arrow.setAttribute("transform",
            "translate(" + arrow.x + "," + arrow.y + ")");
        baseBall.next = arrow;
        arrow.prev = baseBall;
        baseBall.path.setAttribute("points", "");        // (4)
    }

    return ball;
}
delPath() のパラメータ flag は、true の時(1)経路の削除、flase の時(3)経路の描き換えを意味します。削除の時は pathremoveChild() しています(2)が、描き換えの時は path"points" を空文字にする(4)ことで、節点の無い状態にしています。

--------

ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月 6日 (火)

経路の作図 -3-

「経路の作図 -1-」の時点では矢印球の向きは常に一定でしたが、これを線と同じ方向を向くように修正しました。

その解説に先立ち、FlatTable に関わる3種類の座標系について説明します。

1つ目はビューポート座標系です。これはブラウザの表示領域固有の座標系で、原点は左上になります。

2つ目は SVG 座標系です。これは SVG が管理している座標系で、原点は SVG 表示領域の左上です。また、座標スケールがビューポート座標系のものとは異なります。FlatTable は表示領域の寸法に応じて拡大・縮小されて表示されます。その時、SVG 内での px 値は、画像が拡大・縮小されても同じ画像に対しては同じ値を保っています。したがって、ビューポート座標系と SVG 座標系では、1px の実寸は異なることになります。

3つ目は FlatTable 座標系です。この座標系の原点は台のセンタースポットの位置になっています。座標スケールは SVG 座標系と同じです。ball.x, ball.yballFlatTable 座標になっています。これは、プログラムで管理しなければなりません。

これら3種類の座標系には次の関係が成り立っています。

    X = (vX + 原点補正)*mag
    X = x + cX
   (y についても同様)
ここに、X:SVG 座標、vX:ビューポート座標、mag:ビューポート座標系対 SVG 座標系のスケール比、xFlatTable 座標、cX:センタースポット(SVG 座標系)。

ところで、SVG の仕様書によると rotate() のパラメータに関して次のような説明が有ります。

rotate(<rotate-angle> [<cx> <cy>]) は与えられた点を中心とする角度 <rotate-angle> による 回転 を指定する。 <cx>, <cy> が与えられていない場合、回転は現在の利用座標系の原点を中心とする。 もし <cx>, <cy> が与えられているならば、回転は点 (cx, cy) を中心とする。 この変換は次の変換と同値になる:
translate(<cx>, <cy>) rotate(<rotate-angle>) translate(-<cx>, -<cy>)
さて、矢印球の座標は (arrow.x + centerX, arrow.y + centerY) で与えられます(centerX, centerY は台のセンタースポットの座標)。それで、回転は、SVG の仕様書を参考に、次の式
    var x = arrow.x + centerX;
    var y = arrow.y + centerY;
    arrow.setAttribute( "transform",
        "rotate(" + angle + "," + x + "," + y + ")" // angle は回転角度
    );

で実行できると考えたのですが、それでは上手く行きませんでした。矢印球が初期位置に有ればこの式で良いのですが、実際は任意の位置に移動しているので、それを考慮する必要が有ります。

結局、回転は次の手順による変換で実現できます。

  1. 原点(SVG 座標系)を矢印球の位置に移動する
  2. 回転する(中心は原点)
  3. 原点(SVG 座標系)を移動しておいた量のうち、FlatTable 座標の分を除いた残りの分だけ元に戻す
3番目の変換が解りにくいですが、これで上手く行ったので良しとします。これをコードにすると次のようになります。
        球の回転
function drawPath(baseBall){
    var arrow = baseBall.arrow;
    var dx = arrow.x - arrow.prev.x;
    var dy = arrow.y - arrow.prev.y;
    var x = arrow.x + centerX;
    var y = arrow.y + centerY;
    var mx = -centerX;
    var my = -centerY;
    arrow.setAttribute( "transform",
        "translate(" + x + "," + y + ") " +
        "rotate(" + Math.atan2(dy, dx)*180/Math.PI + ") " +
        "translate(" + mx + "," + my + ")"
    );
    ~
}

-4- に続く

ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月 4日 (日)

経路の作図 -2-

― 色の指定 ―

例えば、四角形に座標を設定する時、パラメータの型は数値にします(JavaScript の変数に型が有るのかどうか知りませんが、とにかく、そのようなもの)。下記コードの 72 がそれに当たります。

    rect.setAttribute("x", 72);

それで、polyline の色を指定するのに同じようにRGBを16進表示した数値を指定したのですが、それではダメでした(1)。これを (2) のように文字列 "#??????" にすることで正しい表示が得られました。

    path.setAttribute("stroke", 0xffcc33);    // NG (1)
    path.setAttribute("stroke", "#ffcc33");    // OK (2)

― exPad のZ軸順序 ―

球の移動モードになると exPad(仮想マウスパッド)が現れるようにしているわけですが、これは、ドラッグ中にマウスが球の上を通過しても、その間ドラッグが中断するのを防ぐのが目的です。したがって、exPad は最前面に位置しなければなりません。しかし、現時点では、Z軸順序の処理方法が分からないため、exPad が必ずしも最前面になるとは限りません。exPad が出現した時点では最前面になっているのですが、その後で矢印球やゴースト等が生成されると、それら後から生成された物の方が前面に位置することになります。

しかし、これは反って都合が良いことのように思います。経路作図中は途中でゴーストの位置を微調整するケースが少なくないため、そのゴーストは exPad より前面に有る方が良いのです。

なお、Z軸順序の設定は *.style.zIndex を使うらしいので試してみたのですが、上手く行きませんでした。もう少し調べることにします。

― クリックとドラッグ ―

経路作図中は、マウスボタンを押して動かすと指定しておいた球が移動し、マウスボタンを離すと球の移動が止まります。また、マウスボタンを押した後、マウスを動かさずにマウスボタンを離すと、指定した球の位置にゴーストが生成されます。FlatTable では、この操作を onclick を使わずに実装しました。試していませんが、たぶん、onclick を使うと、ドラッグの時に、同時にクリックと判定されゴーストが生成されるでしょう。

この実装は簡単で、次のようになっています。


function drag(evt){
    fMoved = true;
    ~
}

function dragStop(){
    if (fDraw && !fMoved){
        makeGhost(currentBall);
    }
    ~
}

関数 drag() はマウスボタンが押された時にイベント mousemove に対して設定されるハンドラーです。この drag() 内で、マウスが動いたというフラッグ fMovedtrue にすることで、ドラッグとクリックを区別します。この fMoved は、マウスボタンが離された時に実行される dragStop() 内で検査され、false(マウスは動いていない)ならばゴーストが生成されます。

― 長クッション木枠のクリック ―

長クッション木枠をクリックすると経路作図モードに入り、再度クリックすると経路作図モードを抜けるわけですが、この実装は次のようになっています。


var longRail = document.getElementById("long_rail");
longRail.onclick = makePath;

function makePath(){
    ~
    longRail.onclick = nonDraw;
    ~
}

function nonDraw(){
    fDraw = false;
    longRail.onclick = makePath;
}

makePath() が経路作成の入り口で、nonDraw() が出口です。longRail の click ハンドラーは、初めに makePath に設定され、makePath() 内でそのハンドラーは nonDraw に切り替えられます。そして、nonDraw() 内で makePath に戻されています。

イベント・ハンドラーの設定には addEventListener() を使う方法も有りますが、その場合、ハンドラーの切り替えに removeEventListener() の実行が1つ余計に必要なので、上記コードのように *.onclick にハンドラーを代入する方式を取りました。

-3- に続く

ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

2012年3月 3日 (土)

経路の作図 -1-

Flash 版 FlatTable では、経路作図モードに入るトリガーはダブルクリックでした(球をダブルクリックすると経路作図モードに入る)。SVG+JavaScript 版では、スマートフォンにも対応することを考えているわけですが、スマートフォンでダブルクリックを実装するには、クリック間隔の時間を監視する必要が有ります。しかし、たかがダブルクリックごときでタイマーを監視するのは気が進みません。そこで今回の移植では、トリガーとして何かボタンのような物を使うことにします。そのボタンのような物とは、

長クッションの木枠
Long_frame
です。これをクリックすると経路作図モードに入り、再度クリックすると経路作図モードを出るようにします。因みに、短クッションの方は球の移動モードの解除になっています。

経路作図の動作は次のようになります。

  1. 経路作図モードに入る前に経路を作図する球をクリックしておきます。
  2. その後、長クッションの木枠をクリックして経路作図モードに入ります。
  3. すると、クリックしておいた球の位置に矢印球が出現します。
  4. 球の移動と同じ操作で矢印球を移動させます(矢印球をクリックしておく必要は有りません)。
  5. exPad(仮想的マウスパッド)上でクリックすると、矢印球の位置に経路の節点が作成されます(この時、その位置にゴーストが出現する)。
  6. 予定の経路を作図したら、長クッションの木枠をクリックして経路作図モードを抜けます。
ゴーストや矢印球をクリックしてから経路作図モードに入ると、その部分に経路が追加されます。また、既に経路が作成されている基礎球(ゴーストや矢印球ではない最初の球)をクリックしてから経路作図モードに入ると、それまでの経路がキャンセルされて、新たな経路の作図が始まります。

経路は SVG の要素 polyline で構成します。マウスの動きに合わせてインタラクティブに経路を描画するには、Flash だと MovieClip の clear() と lineTo() を使いますが、polyline には、lineTo() に相当するものが有りません。また、SVG のプロパティ display をnone に設定すれば非表示にすることは出来ますが、それが Flash の clear() に相当しているとは思えません。そういう訳で、インタラクティブな経路の描画に polyline が使用できるのか心配でした。

ところで、polyline には次のような属性が有ります。

  • points="節点の座標"
  • fill="塗りつぶしの色"
  • stroke="線の色"
  • stroke-width="線幅"
  • その他いろいろ
この属性を使って、どうやって Flash の clear() や lineTo() のようなことが出来るのでしょうか? しばらく悩んだのですが、分かってみると答えは簡単でした。points を書き換えてやれば良いだけでした。特別に clear() なんてことは必要無かったのです。

コードは、こうなります。

function makePath(){ ~ var path = document.createElementNS(svgns, "polyline"); path.setAttribute("style", "fill:none;~"); // (1) ~ baseBall.path = path; flattable.appendChild(path); ~ } function drawPath(baseBall){ var ball = baseBall; var points = ""; do { var x = ball.x + centerX; // (2) var y = ball.y + centerY; points += x + " " + y + " "; } while (ball = ball.next); baseBall.path.setAttribute("points", points); }

ここで注意することが2つ。1つ目は、fill を none にしないと polyline が多角形のごとく塗り潰されるということです(1)。2つ目は、ball.x や ball.y で表されている座標はセンタースポットを原点とした時の座標であるのに対して、polyline の座標は SVG 本来の座標(つまり、原点は左上)であることです。この2つ目より、上記コード内の x, y には centerX, centerY のオフセットが繰り込まれています(2)。

-2- に続く

ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。現時点では矢印球の向きが経路の傾きに同調していませんが、これは後日対応する予定です。

« 2012年2月 | トップページ | 2012年4月 »