Home > ActionScript

Web 酒 肴

«前へ || 1 | 2 | 3 || 次へ»

Flex Builder 改め Flash Builder になるそう

FlashとFlexの区別がなかなかつかなかった僕ですが、その原因の一つはまさにこれだった。

Flex Builder “Gumbo” is Being Renamed Flash Builder | Ryan Stewart - Rich Internet Application Mountaineer

Flex Builderという名前をFlash Builderに改める予定とのこと。

僕がなぜFlexとFlashの区別がつけられなかったかというと、それはFlashの文化を知らずにFlex Builderを触ったから。 Flex BuilderはFlex SDKを使ったアプリケーションを手軽に構築できるが、Flex SDKを使わないFlashアプリケーションも作成できる。でもFlex Builderと言うからには、これを使って作ったアプリケーションは全てFlexじゃないの?なんて思ってた。

そこが違った。

Flex Builderを使ってもFlex SDKを使わなければそれは単なるFlashアプリケーションなのだ。 じゃあ自分の作ったアプリケーションがどれほどFlex SDKに依存しているのかは、それまでFlashの経験がない自分には区別が難しい。 さすがにMXMLとか使ってたら、ああこれはFlexだと思うが、AcstionScriptのみで作成したアプリケーションが内部的にFlex SDKで提供されているクラスを参照している場合なんかもあるのだろう。

ここから先は知識を増やして憶えていくしかないのだろうけど、今回の名前変更で最初の誤解をする人が減るのはいいことだと思う。

[ActionScript]2直線の交点を求める

先日作ったライブラリを利用すると以下のようなことができます。

画面内でマウスをクリック&ドラッグしてください。 線分同士の交点を表示します。

直線や線分の交点を計算する - wonderfl build flash online

そんなに大したことはしてませんが、あえてLineクラスの特徴をあげるとするならば線分、半直線、直線に対応していることか。 多くの場合は線分同士の交点を求めればいいのであまり使わないけど。

Lineクラスは以下のように使用します。

//Lineインスタンスを2つ作成
var line1:Line = new Line(new Point(x1, y1), new Point(x2, y2), Line.TYPE_SEGMENT); //Line.TYPE_SEGMENTは線分
var line2:Line = new Line(new Point(x3, y3), new Point(x4, y4), Line.TYPE_HALF); //Line.TYPE_HALFは半直線

//交点の座標を取得
var p:Point = line1.getIntersectionPoint(line2);

交点がない場合は null が返ります。

Lineクラス内では交点を求める以外にもいくつかのチェックなどしていますが、実際に交点を求めるところのアルゴリズムだけを抜き出すと以下のようになります。

// a1,a2を通る直線とb1,b2を通る直線をあらわすベクトル作成(a1, a2, b1, b2は全てPointオブジェクト)
Point a = a2 - a1;
Point b = b2 - b1;

//crossは2つのベクトルの外積を計算するメソッド
return a1 + a * cross(b, b1-a1) / cross(b, a);

参考にしたのはここ。 平面幾何におけるベクトル演算 » 直線と線分

Lineクラスのソースコードは以下。

Line.as

package
{
    import flash.geom.Point;

    public class Line
    {
        /* 2点を通る直線(終端はない) */
        public static const TYPE_STRAIGHT:String = "straight";
        /* p1からp2の方向に延びる半直線 */
        public static const TYPE_HALF:String = "half";
        /* p1, p2間の線分 */
        public static const TYPE_SEGMENT:String = "segment";

        public var p1:Point;
        public var p2:Point;
        public var type:String;

        public function Line(p1:Point, p2:Point, type:String=TYPE_STRAIGHT)
        {
            this.p1 = p1;
            this.p2 = p2;
            this.type = type;
        }

        /**
         * 2つのLineインスタンスの交点を表わすPointインスタンスを取得する
         * 交点がない場合はnullを返す
         * @param line
         * @return 
         * 
         */
        public function getIntersectionPoint(line:Line):Point{
            var vector1:Point = this.getVector();
            var vector2:Point = line.getVector();

            if(cross(vector1, vector2) == 0.0){
                //2直線が並行の場合はnullを返す
                return null;
            }

            // 交点を this.p1 + s * vector1 としたとき
            var s:Number = cross(vector2, line.p1.subtract(this.p1)) / cross(vector2, vector1);
            // 交点を line.p1 + t * vector2 としたとき
            var t:Number = cross(vector1, this.p1.subtract(line.p1)) / cross(vector1, vector2);

            if(this.validateIntersect(s) && line.validateIntersect(t)){
                vector1.x *= s;
                vector1.y *= s;
                return this.p1.add(vector1);
            }else{
                return null;
            }
        }

        public function getVector():Point{
            return p2.subtract(p1);
        }

        /**
         * 交点までのベクトルを p1 + n * (p2 - p1) であらわしたとき、
         * nが適切な値の範囲内かどうかを判定する。
         * 
         * 直線の場合:nはどの値でもよい
         * 半直線の場合:nは0以上である必要がある
         * 線分の場合:nは0以上1以下である必要がある
         * @param n
         * @return 
         * 
         */
        private function validateIntersect(n:Number):Boolean{
            if(this.type === TYPE_HALF){
                return (0 <= n);
            }else if(this.type === TYPE_SEGMENT){
                return ((0 <= n) && (n <= 1));
            }else{
                return true;
            }
        }

        /**
         * 2つの2次元ベクトルの外積を返す
         * @param vector1 2次ベクトルを表わすPointインスタンス
         * @param vector2 2次ベクトルを表わすPointインスタンス
         * @return 
         * 
         */
        private function cross(vector1:Point, vector2:Point):Number{
            return (vector1.x * vector2.y - vector1.y * vector2.x);
        }

        public function toString():String{
            var str:String = "";
            if(type === TYPE_STRAIGHT){
                str += "---> ";
            }
            str += "(" + p1.x + ", " + p1.y + ") ---> (" + p2.x + ", " + p2.y + ")";
            if(type === TYPE_STRAIGHT || type === TYPE_HALF){
                str += " --->";
            }

            return str;
        }
    }
}

[Flex]カスタムエフェクトの作成 #7 - 2直線の交点を求める

久しぶりにこれに取り掛かれる。 5/30のFlex3勉強会第70回@京都までに完成させなくてはいけないので、のんびりしてられないわけだけど、ここにきてまたバンド組んだり知り合いのHP頼まれたり、会社で大がかりな組織変更があってその対応とか、しばらく大変そう・・・。

このエフェクトをきれいにライブラリ化するために、どうしても2つの線分の交点を求める処理が必要になってくる。 どうせならこれも汎用的に使えるようにしようと思って、以下のようなLineクラスを作ることにした。

Lineクラス概要

  • Lineクラスのインスタンスは一つの直線・半直線・線分を表わす
  • (半)直線または線分上にある2つの座標(x1, y1)(x2, y2)によって初期化される
  • 初期化時のパラメータにより、直線・半直線・線分のいずれかを指定することができる
  • 別のLineクラスのインスタンスを引数に取り、お互いが交差している座標を返すgetIntersectionPointメソッドを持つ

これを作成するにあたり、線分の交点を計算するアルゴリズムをいろいろ調べた結果、今回はここを参考にするのが一番目的にあっていそう。

平面幾何におけるベクトル演算 » 直線と線分

あと、今更ながら知って驚いたこと。

ActionScript3ではコンストラクタを複数定義できないっぽい

ちょっと残念。

[ActionScript][アニメーション]Flex勉強会@京都開催しました

先日(2/7)、京都でFlex勉強会を開催しました。20人以上の方が参加してくださり、おかげさまでその後の懇親会も含めて大変盛況でした。 会場を提供してくれた上、様々なご協力をいただいたソフトディバイスさん、本当にありがとうございました。

僕もActionScriptでのアニメーション入門を少し発表したので、その時の資料に少し手を加えたものを掲載しておきます。 wonderflというサービスを使い、ソースコードとサンプルを画面上で見れるようにできました。 便利ですね。

[Flex]調和級数の部分和計算フォーム

調和級数がどのように増加するのかを検証するために、調和級数の部分和を計算するツールを作りました。

PCスペックにもよりますが、x = 1000000(ひゃくまん)を入力するとアホほど時間がかかります。 なので1,000,000より上は入力できないようにしました。

計算結果は分数と小数両方表示します。 分数計算がめんどくさそうだったけど、ユークリッド互助法使って最大公約数を出す関数作ったら、それ使って最小公倍数も出せて結構簡単に 通分とか約分ができた。

上記2関数のソースを一応載せときます。

public class MathFunctions
{
    /**
     * 最大公約数を計算する 
     * @param m
     * @param n
     * @return 
     * 
     */
    public static function gcf(m:Number, n:Number):Number{
        //負の数の場合は正の数に変換
        m = Math.abs(m);
        n = Math.abs(n);

        while(true){
            if(m < n){
                var tmp:Number = m;
                m = n;
                n = tmp;
            }

            if(n == 0) return m;

            if(m % n == 0){
                return n;
            }else{
                m = m % n;
            }
        }

        return 0;//コンパイルエラーを防ぐため(実際にはここに到達することはない)
    }


    /**
     * 最小公倍数を計算する 
     * @param m
     * @param n
     * @return 
     * 
     */
    public static function lcm(m:Number, n:Number):Number{
        var gcf:Number = gcf(m, n);
        return m / gcf * n;
    }
}

[FLex]ゆるふわ掲示板 in 変なプログラマーの作り方

変なプログラマーの作り方という勉強会でプレゼンターをしました。 主催者が同じ会社のfujioka0729だったこともあり、お願いされたというわけです。 会社の仕事がかなり厳しいこのタイミングに振ってくるとは中々にSな奴です。 ま、僕はMなので受けたわけですけど。

テーマが掲示板ということなので、Flexでゆるふわ掲示板を作ってその紹介をしてきました。 「変な」というテーマを目指していたはずが、いつの間にかそれを忘れてて、最終的にはそれほど変わったものにならなかったというのが反省点かな。 作ったものはこちら。

「ゆるふわ掲示板」

  1. 画面上でクリックするとその周辺の書き込みを表示後、その位置に書き込むフォームが表示されます
  2. 頑張って探さなくとも色んな穴があるので、優しさを持って接してください。怖いので、多分そのうち削除しますけど。

まあ色々と手を抜いてる部分があるのですが、下のほうでソースでも晒しておきます。 (手を抜いているからこそソースを読んでも何が何やらわからない → わからないから手を抜いてるとわかる、みたいな。)

勉強会は会社の知人の出席率が高く、盛り上がりました。今後は幅広く色んな人が参加してくれれば楽しくなりそうですね。 毎回、投票で最も「変な」プログラマが選出される、というのが特色です。

そしてなぜか今回は僕が選ばれてしまいました。 自分で自分に投票するという節操のなさが勝因でしょう。 他にはこんなことをした方がいました。

カップラーメンより早く掲示板を作る by fujioka0729

  • Railsを使ってその場で掲示板を作る
  • その後、一行ずつアニメーションで表示するようなJavaScript処理を追加
  • 全てその場でライブコーディングしたので、かなりテンパッてて面白かった

バッチファイルで掲示板作りに挑戦してみた by 崎さん

  • Windowsのコマンド、いわゆるバッチファイルでサーバサイドの処理を作るというもの
  • CGIのインターフェースを利用
  • 「変なプログラマ」という勉強会の趣旨には一番あってたのではないかと思われる

上記の2人は主催者でもあります。 参加した皆さん、お疲れ様でした。 また会いましょう。

続きを読む

[翻訳]Flex3 Cookbook 1.11 イベントバブリングの使用

Flex3 Cookbookが不親切な上に誤植があったため、ついでに翻訳してみる。 僕が英語読めてないだけだったりして。

とってもテキトー翻訳だと断っておきます。

3つのMXMLファイルのソースが出てきますが、BubblingComponent.xml, BubblingComponentHolder.mxmlはソースの配置場所に以下のフォルダを作成し、そこに配備してください。

oreilly/cookbook

上記2ソースの先頭にある

xmlns="oreilly.cookbook.*"

で察しろということなんだろうけど、僕はいまいちその辺の知識がないので少しハマりました。

1.11 Use Event Bubbling の翻訳

課題

あなたは子要素のコンポーネントから親要素のコンポーネントへと順次呼び出されるイベント処理を書きたい。 もちろんイベントリスナ内で呼び出し処理を書くというような手間のかかる方法ではなく。

解決法

子要素から順次通知されるイベントバブリングの仕組みを使いましょう。

検討

イベントのバブリングを理解するにはいくつかのクラスを作成してみる必要があります。 MOUSE_DOWNイベント、CLICKイベント、KEYBORDイベントなど、いくつかの種類のイベントを発生させることができます。 バブリングという言葉はイベントがディスプレイの階層をアプリケーションコンテナまで上っていく様子をあらわします。 泡が水中を上っていくかのように。

ユーザが何らかのコンポーネントをクリックしたとき、そのイベントはコンポーネントの階層を上っていきます。 つまり親コンポーネントは子コンポーネントのクリックイベントを監視し、子要素で発生したイベントを検知できるということです。 親コンポーネントに、子要素のある種類のイベントすべてを監視させるには、単に子コンポーネントの記述部にリスナを追加すればよい。

oreilly/cookbook/BubblingComponent.mxml

<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="200">
    <mx:Script>
        <![CDATA[
            private function sendClick():void
            {
                trace(" BubblingComponent:: click ");
            }
        ]]>
    </mx:Script>
    <mx:Button click="sendClick()"/>
</mx:HBox>

上記のコンポーネントはボタンを保持しており、そのボタンはクリックイベントを発生させる。 そのイベントはBubblingComponentのインスタンスを保持するコンポーネントにイベントを伝えていく。 そのイベントを検知するにはBubblingComponentを含むコンポーネント内でクリックハンドラを用意すればよい。

<cookbook:BubblingComponent click="handleClick()" id="bubbler"/>

上記の要素を含むようにBubblingComponentHolderを以下のように作成する。

oreilly/cookbook/BubblingComponentHolder.mxml

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" 
xmlns:cookbook="oreilly.cookbook.*">
    <mx:Script>
        <![CDATA[
            private function handleClick():void
            {
                trace(" BubblingComponentHolder:: click ");
            }
        ]]>
    </mx:Script>
    <cookbook:BubblingComponent click="handleClick()" id="bubbler"/>
</mx:Canvas>

上記のコンポーネントは他にもイベントを監視するコンポーネントがあれば、アプリケーションレベルまでイベントを通知する。 メインアプリケーションBubblingHolderを作成すればBubblingComponent.mxmlで発生したクリックイベントは最終的にアプリケーションレベルにまで通知される。

BubblingHolder.mxml

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:cookbook="oreilly.cookbook.*">
    <mx:Script>
        <![CDATA[
            public function createName():void{
                name = "Flex Cookbook";
            }
        ]]>
    </mx:Script>
    <cookbook:BubblingComponentHolder/>
</mx:Application>

MouseEventの一連のイベントはクリック位置などの付属情報を、それを監視する子要素を持つコンポーネント階層を特定し、Stageにイベントを通知する。

StageMouseEventを検知すると先ほどのコンポーネント階層を、ユーザがマウス操作した最後のコンポーネントにたどり着くまでイベントを通知していく。 これはキャプチャリングと呼ばれる。次にイベントを処理すべきイベントハンドラが実行される。これはターゲッティングと呼ばれ、イベントに実際のターゲットが与えられる段階である。最後にバブリングの段階に入り、コンポーネント階層をさかのぼってStageまで順にイベントを通知する。

«前へ || 1 | 2 | 3 || 次へ»

Home > ActionScript

Search
Feeds

Page Top