[AS][?]画像のEmbedは1回しか使えない?
よくわからんけど、他のクラスでEmbed済みの画像を別のクラスでEmbedしても表示もされなかった。
エラーも出ないから、かなりはまった。
とりあえず、あとで検証する。
よくわからんけど、他のクラスでEmbed済みの画像を別のクラスでEmbedしても表示もされなかった。
エラーも出ないから、かなりはまった。
とりあえず、あとで検証する。
先日、東京てらこ 9に参加してきました。
Twitterで何かつくろうってテーマだったのAirアプリを作ってみました。
「Twittenorion」


タイトルどおりTweetのテキストでテノリオンするという感じです。
SEARCH WORDを入力しSEARCHボタンを押すと、入力してワードでのTwitterで検索を行い結果の20件をランダムで順番に表示さいていきます。
DRUM KITのON/OFFの際にはドラムパターンがランダムに変更されます。
BPMにあわせて流れる文字の速度が変化します。
集中したいときの作業用BGMになるかなってつもりで作りました。
以下からDLできますので、気になった人は試してみてくださいませ。
DownLoad : Twittenorion
またてらこでの発表資料のスライドもアップしておきます。
東京てらこ vol.9 発表資料
(キーボードのカーソルキーでスライドの操作ができます)
・キーボードから任意の文字を入力できるようにしたものをwonderflにアップしました。
Twittenorion – wonderfl build flash online
MovieClipにおいて、特定のフレームのフレームアクションを実行することができるメソッドがあります。
任意のフレームのスクリプトを実行:frame + “フレーム数” + ();
たとえば、ステージに_mcというインスタンス名でMovieClipが配置してある場合。
(_mcには1,2,3フレームにスクリプトが書いてある)
frame+フレーム数というメソッドを実行することができます。
//_mc:ステージに配置してあるMovieClipインスタンスで
//1,2,3フレームにスクリプトが書いてあり、内容は以下の通り
//1フレーム目には、trace("_mc 1フレーム");
//2フレーム目には、trace("_mc 2フレーム");
//3フレーム目には、trace("_mc 3フレーム");
_mc.frame1(); //出力:_mc 1フレーム
_mc.frame2(); //出力:_mc 2フレーム
_mc.frame3(); //出力:_mc 3フレーム
このとき以下のようなエラーが発生するときがある。
TypeError: Error #1006: frame1 は関数ではありません。
at _fla::MainTimeline/frame1()
このときの原因の一つは、実行対象のMovieClipにリンケージ指定されているということ。
リンケージ指定した状態で、任意のフレームのスクリプトを実行しようと上記のようなエラーになるらしい。
また、動的に生成したMovieClipインスタンスについても、addFrameScript()メソッドでフレームにスクリプトを追加した場合についても、同じ結果になるようす。
以下、例
var mc:MovieClip = new MovieClip();
addChild(mc);
//ムービークリップの1フレーム目にファンクション:testを追加
mc.addFrameScript(0,test);
function test():void{
trace("mc script")
}
mc.frame1()//上記のようなエラーが発生する
ということは、動的に生成したmcにaddFrameScript()でファンクションを追加しても実行する術はないということ!?
まぁ理由はわからないけどそんな挙動をするみたい。
まぁ、こんなのそうそう使わないけども。
一般的にMovieClipとSpriteの違いは、
・MovieClip:タイムラインを持てる。
・Sprite:タイムラインを持てない。
リファレンスを見てもMovieClipはSpriteのサブクラスであり、タイムライン操作についてのメソッドが追加されたものとなっている。
////////////////////////////////////////////////////////////////////////
・そもそも「タイムラインを持っている」とは具体的に何なのか?
フレームを2フレーム以上持っている状態を指すらしい。
参考:ActionScript3.0入門ノート|Spriteの作成と表示
つまり
・MovieClip:フレームを2フレーム以上持てる。
・Sprite:フレームを1フレームだけ持てる。
こういうことになるのでしょう。
////////////////////////////////////////////////////////////////////////
・ここで疑問なのです。
FlashIDEではドキュメントクラスをSpriteを継承したクラスを指定することができますよね。
この場合、メインタイムラインはSprite扱いということになると思うのですが、実際はそうではないようです。
以下の画像のような状態の場合、

これをパブリッシュすると、青い四角が点滅する状態となります。
ドキュメントクラスをSpirteにしているのに、メインタイムラインは2フレーム目以降も繰り返し再生されているのです。
ちなみに、この際フレームにstop();等のスクリプトを書くと、errorとなります。
これは、フレームにスクリプトが書けるのはMovieClipだけだからという理由です。
具体的にはフレームにスクリプトを書くという行為は、内部的にはaddFrameScript()というメソッドで実装されているようで、SpirteにはこのaddFrameScript()メソッドが定義されていないから、ということのようです。
つまり、ドキュメントクラスをSpriteで定義した場合(のメインタイムライン)は、完全なSpriteでもなく、またMovieClipでもないというような中途半端な存在に思えるのです。
////////////////////////////////////////////////////////////////////////
ちなみにMovieClipとしてライブラリに登録したシンボルの基本クラスをSpriteとし、
そのシンボルのタイムラインを10フレームにした場合について、
(下画像参照)
このシンボルをステージに置いた場合のシンボルの挙動はどうなると思いますか?
先ほどのように2フレーム目以降が繰り返し再生されるのでしょうか?
答えは、黒いシェイプは点滅しません。
1フレーム目のみが描画された状態でstop();状態となり、2フレーム目以降は無視されているようです。
これが本来のSpriteの挙動であると思います。
////////////////////////////////////////////////////////////////////////
メインタイムラインだけが特別な扱いになっているのでしょうか?
こういうもんだと思えば実害は無いのですが、なんか気持ち悪いですよね。
この理由をご存知の方いましたら是非ご教授くださいませ。
テスト環境:winXP FlashCS5
TweetAdobe推奨が以下のリンク
Flex SDKコード記述に関する規則とベストプラクティス
あくまでFlexSDK用っぽいので、FlashIDEがこれに準拠するかといったら微妙っぽい。
たとえば、{で改行をどこにいれるかという点では、
FlashIDEで、function生成のショートカットキーESC+f+nで生成されるコードは、
function () {
//処理
}
規約では、{を整列させると書かれている
function ()
{
//処理
}
とはいれ、それ以外の部分は大体真似していいんじゃないかと。
◆気になった部分だけmemo
・new Array() → []
・new Object() → {}
・if(flag == true) → if(flag) (flag:Boolean,Object)
・as演算子よりもキャストを使う
・単純な条件はifよりも三項演算子を使う (ifより遅くなるんじゃないの?)
・if文が(全ての項目のステートメントが)一項目のときはブロック{}を書かない
・for、while、do文では必ずブロック{}を書く
・protected override → override protected
・static public → pubilc static
・定数は全てstaticとする
・変数を初期化するときはコンストラクタではなく宣言時にする。
?なところもあるけど一通り目を通しておいてもよさげ。
Tweet製作の上であったら便利かな、と思ったのでクラス化。
◆動機
たとえば、あるボタンを押したら外部読み込み開始するとしたら、それが失敗したときなどを考慮してにエラー処理を実装しますよね。
この実装のチェックとしては、わざとエラーが起こる状態を再現してテストしなくちゃいけない。
たとえば、読み込むべきURLが外部xmlに記述してあって、それが存在しないURLだった場合のエラー処理だったら、わざとxmlに記述されたURLを間違えたものに書き換えてチェックとか。
というようなことを以前はやってました。
が、いちいちファイル書き換えてチェックするのが面倒。
そこで、
もしshiftキーを押しながらクリックしたら、存在しないURLを読みにいくようなロジックを最初から組んどけばテスト簡単じゃね?
お客さんにエラー時の動作処理をみてもらうときも、お客さんの負担減るんじゃね?
ってことで、shiftキーとctrlキーが押されてるかどうかを判定するクラスを作りました。
Singletonで作ってあるので、最初に初期化しちゃえば、どこからでも参照可能。
消すときも、Singletonなのでクラス名で検索書ければどこで使ってるかが一目瞭然(のはず)。
使い方は以下のような感じ
//準備
//ステージに追加、これだけでOK
addChild(AddKeyDownUtil.getInstance());
//使い方、以下のプロパティを参照して、true/falseを取得できる
//シフトキーが押されてたら、true,押されてなかったらflaseを返す
AddKeyDownUtil.getInstance().isShiftDown;//戻り値:Boolean
//コントロールキーが押されてたら、true,押されてなかったらflaseを返す
AddKeyDownUtil.getInstance().isCtrlDown;//戻り値:Boolean
//使用例)
//_btnがクリックされたときにシフトキーが押されているかいないかで処理を分岐
_btn.addEventListener(MouseEvent.CLICK, clickHandler);
private function clickHandler(e:MouseEvent):void {
if(AddKeyDownUtil.getInstance().isShiftDown){
//シフトキーが押されていた場合に実行したい処理
}else{
//シフトキーが押されていない場合に実行したい処理
}
}
クラスファイルは以下の通り
package bz393.util {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
/**
* ...
* @author 393
*/
public class AddKeyDownUtil extends Sprite{
public static var instance:AddKeyDownUtil;
public var isShiftDown:Boolean = false;
public var isCtrlDown:Boolean = false;
public function AddKeyDownUtil(enforcer:SingletonEnforcer) { };
public static function getInstance():AddKeyDownUtil {
if (!AddKeyDownUtil.instance) {
AddKeyDownUtil.instance = new AddKeyDownUtil(new SingletonEnforcer());
AddKeyDownUtil.instance.addEventListener(Event.ADDED_TO_STAGE,init);
}
return AddKeyDownUtil.instance;
}
static private function init(e:Event):void {
AddKeyDownUtil.instance.removeEventListener(Event.ADDED_TO_STAGE, init);
AddKeyDownUtil.getInstance().stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHander);
AddKeyDownUtil.getInstance().stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHander);
}
static private function keyDownHander(e:KeyboardEvent):void {
switch (e.keyCode) {
case Keyboard.SHIFT:
AddKeyDownUtil.instance.isShiftDown = true;
break;
case Keyboard.CONTROL:
AddKeyDownUtil.instance.isCtrlDown = true;
break;
}
}
static private function keyUpHander(e:KeyboardEvent):void {
switch (e.keyCode) {
case Keyboard.SHIFT:
AddKeyDownUtil.instance.isShiftDown = false;
break;
case Keyboard.CONTROL:
AddKeyDownUtil.instance.isCtrlDown = false;
break;
}
}
}
}
class SingletonEnforcer {
};
Tweet
あまり意味のない情報だけど数時間ハマったのメモしとく。
まず結論から書くと、これはムービープレビューのときのみ発生(FlashCS4で確認)
ムービープレビューのときに立ち上がるFlashPlayerはブラウザに埋め込まれてるプレイヤーとは異なるもの。
まれにおかしな挙動をすることがあるのだけど、今回もその類のバグだったわけ。
なので、実際にブラウザ上で確認すれば題記のような現象にはならない。
一応再現手順を書いておく。
1.flaファイルに日本語フォントを埋め込む。(小塚ゴシックProBとする)
2.ASにて、動的にTextFieldを配置(フォントサイズを16とかに)
3.TextFieldに埋め込んだフォントを設定
4.stage.qualityをMedium以下に設定
5.TextFieldの3Dプロパティを変更(z=0とか)
6.ctrl+enterでムービープレビュー
7.指定したフォントサイズよりもでかく表示される
※stage.quailtyをHIGH以上にすれば上記現象はおきません。
まぁ実害はないけど遭遇したら一瞬焦るので一応覚えておいたほうがいいかも。
Tweetすげー、はまったのでメモ。
↓の問題でした。
[AS]フォント名を指定するときの注意(日本語?英語?)
(今、このを記事書いてるときに上のエントリーに気付いた。アホすぎる。。。)
上の記事では、FlashIDEとFlexSDKでフォント名が異なる?という内容だけど、
FlashIDEでもバージョンによってはフォント名が異なることが発覚。
※windows/mac、Flashの日本語版/英語版で結果が異なるかも
※今回検証したのはwindow、日本語版
例1)小塚ゴシックPro レギュラーの場合
CS3:小塚ゴシック Pro R (日本語で指定)
CS4:Kozuka Gothic Pro R (ローマ字で指定)
CS5:Kozuka Gothic Pro R (ローマ字で指定)
CS3は日本語で指定だったけど、CS4以降はローマ字で指定。
・ちなみにボールドの場合はまた違った感じに。。。
例2)小塚ゴシックPro ボールドの場合
CS3:小塚ゴシック Pro B (日本語で指定)
CS4::Kozuka Gothic Pro B (ローマ字で指定)
CS5:小塚ゴシック Pro B (日本語で指定)
もちろん、日本語で書くべきところをローマ字で書いたりしたら、フォントは指定されない。
同じフォントなのにスタイル違いで、書き方変わるなんてそんなのわからんよ。。。
というわけでフォント名は直接文字列で書くのではなく、FontクラスのfontNameプロパティを使った方が間違いがおきなそう。
//ライブラリにフォントを追加 //ASに書き出しにチェック //クラス名を指定 (仮にMyFontとする) var myFont:Font = new MyFont(); myFont.fontName;//フォント名 var tfm:TextFormat = new TextFormat(); tfm.font = myFont.fontName;//文字列で指定しない。Tweet
ダイナミックテキストへのフォント指定での挙動について。
CS5から挙動が変わってることに気付いたのでメモ。
◆手順
1.FlashIDEにて、ステージにダイナミックテキストを置く。
2.ダイナミックテキストに何か文字(ここでは”あいうえお”とする)を入力。
3.ダイナミックテキストに任意のフォント(ここではA-OTF 新ゴ Pro Bとする)を指定。
(ここでフォント:A-OTF 新ゴ Pro Bは埋め込まない)
4.パブリッシュ
5.フォント(A-OTF 新ゴ Pro B)が入っていないPCで表示を確認。
◆結果
・CS4でパブリッシュした場合
→文字が、デバイスフォントで表示される。
・CS5でパブリッシュした場合
→文字が、指定フォント(A-OTF 新ゴ Pro B )で表示される。
つまり、CS4ではフォントの埋め込みは行われないが、CS5ではフォントが埋め込まれている。
またここでは、入力した文字(あいうえお)のみが埋め込まれているので、動的にtextを変更しようとしても使える文字は”あいうえお”だけとなる。
というわけで、これをCS4でも同様の挙動をさせるには、
1.ダイナミックテキストを選択
2.プロパティパネルの「文字の埋め込み」をクリック
3.「自動読み込み」ボタンをクリック。
→ダイナミックテキストの文字列(ここでは”あいうえお”)が埋め込み対象文字となる。
4.「OK」をクリック
これでOK。
つまりCS5からは、上記の埋め込み作業を自動でやってくれるようになったようだ。
嬉しいような、こんがらがるような。。。
感覚的に勘違いをしていたのでメモしておく。
言葉で書いてもうまく伝えられないので、まずは以下フレームアクションのスクリプト参照。
import flash.display.Sprite; //1階層目 //コンテナ的sp(塗り無し) var container01:Sprite = new Sprite(); //コンテナの背景的なもの(赤塗り) var bg01:Sprite = new Sprite(); bg01.graphics.beginFill(0xFF0000); bg01.graphics.drawRect(0,0,300,300); bg01.graphics.endFill(); //ボタン的なもの var btn01:Sprite = new Sprite(); btn01.graphics.beginFill(0x660000); btn01.graphics.drawRect(40,40,40,40); btn01.graphics.endFill(); btn01.buttonMode = true; //コンテナ的なものをメインのタイムラインに配置 this.addChild(container01); //背景的なものをコンテナに配置 container01.addChild(bg01); //ボタン的なものをコンテナに配置 container01.addChild(btn01); ////////////////////////////////////// //2階層目 //コンテナ的sp(塗り無し) var container02:Sprite = new Sprite(); //1階層目が見えるように半透明にして配置をずらす container02.alpha = .5; container02.x = container02.y = 20; //コンテナの背景的なもの(青塗り) var bg02:Sprite = new Sprite(); bg02.graphics.beginFill(0x0000FF); bg02.graphics.drawRect(0,0,300,300); bg02.graphics.endFill(); //ボタン的なもの var btn02:Sprite = new Sprite(); btn02.graphics.beginFill(0x000066); btn02.graphics.drawRect(40,40,40,40); btn02.graphics.endFill(); btn02.buttonMode = true; //コンテナ的なものをメインのタイムラインに配置 this.addChild(container02); //背景的なものをコンテナに配置 container02.addChild(bg02); //ボタン的なものをコンテナに配置 container02.addChild(btn02); //1階層目のボタンを押せるようにするには、 //2階層目の背景的なものをmouseEnabled = false bg02.mouseEnabled = false; //さらに、コンテナ的なspもmouseEnabled = false; //にしないとだめ container02.mouseEnabled = false;
はまったポイントは2階層目のコンテナ自身に対してもmouseEnable=falseを設定してあげないといけないということ。
2階層目のコンテナ自身は塗りを持ってないから、(塗りの実体である)背景だけをmouseEnable=falseにすればいいんじゃね、と思い込んでおりましたが、それだと1階層目のボタンに触れません。
コンテナ自身もmouseEnabled=falseにしてやらないとだめだったのです。
感覚的に、コンテナをmouseEnabled=falseにしちゃったら、コンテナが内包しているボタンもmouseEnabled=false扱いとなってしまうかと思ったら、そんなことは無いというオチ。
mouseChildrenってプロパティもあるし、それぞれの機能をちゃんと理解しとかないとマズイです。。