Think About it



Home > Blog

20080125

Flash + HTML(2)


HTML側からFlashに変数を渡す場合、
以前に書いたように
swfを読み込んでいる部分に&をつけることで簡単に処理できます。

それと似たような処理で、表示しているHTMLのURLから変数を渡してみます。
(javaScriptがメインとなります)

考え方としてはswfのURLに直接変数を書き込む方法と同じで、
HTMLのURLの末尾に変数を付加し、
それをJavaScriptで読み込み、
それをswfに渡す、という方法になります。

具体例。

swfを読み込む側のHTMLに以下のJavaScriptを記述。
var str = location.search;
str = str.substring(1,str.length);


このページへのリンクを以下のように記述。
<a href="xxxx.html?1">Link</a>


これで、読み込み側のHTMLの変数、strに、「1」が入ります。
※location.searchで、URLの?からを取得できます。
この例では、「?1」となります。
なのでそこから1だけを、substringで取り出しています。

あとは、この変数をswfに入れてやるだけです。

これは、swfを読み込んでいる部分をJavaScriptで吐き出すように書いてやり、
swfのURLの後ろに、&=strといれてやるだけです。

・param
document.write('<param name="movie"
value="xxxx.swf?flag='+str+'">\n');

・embed
document.write('<embed src="top.swf?flag='+str+'" quality="high"
bgcolor="#ffffff" width="750" height="214"
align="" type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer">\n');

※swfのURLを読み込むところのみ記述。
どっちも一行です。

これを、FlashVarsを用いて、変数を渡してやることもできます。
document.write("<param name=\"FlashVars\" value=\"flag="+str+"\" />");

・embedは割愛。

さらに、これをswfObjectを使用するとさらに簡単になります。
記述部分に、以下のパラメータを足してやるだけです。
so.addVariable("flag", str);

詳しくはこちら。

FLASH-JP.COM フォーラム - リンクされたURLの引数を変数として受け取る。

参考:
A LOT - JavaScriptで変数受け取りの巻

----------------------------------------------------------------------------------------------------

20080115

function(1)


ボタン等の処理をフレームアクションで書く場合。

今まではそのまま書いてました。

例:
押したボタンの番号を表示させる。

表示させる部分の関数は以下。(この部分は後ほども使い回します)
function testTxt(num){
test_txt.text = num;
}

本体は以下。
btn0.onPress = function(){ testTxt(0);}
btn1.onPress = function(){ testTxt(1);}
btn2.onPress = function(){ testTxt(2);}
btn3.onPress = function(){ testTxt(3);}
btn4.onPress = function(){ testTxt(4);}
btn5.onPress = function(){ testTxt(5);}
btn6.onPress = function(){ testTxt(6);}
btn7.onPress = function(){ testTxt(7);}
btn8.onPress = function(){ testTxt(8);}
btn9.onPress = function(){ testTxt(9);}



こんな感じで、列記していました。

これをもうちょっとスマートに、まとめて書けないものかと。
(これだと、増やしたり減らしたりするのにめんどう)

で、for文で単純に回してみました。

function setBtn(){
for( i = 0; i < 10; i++){
this["btn"+i].onPress = function(){ testTxt(i);}
}
}
setBtn();



で、結果を見ていただければわかる通り、おかしい、です。
どのボタンを押しても、「10」が表示されます。

色々試してみた結果、どうやら以下のようです(あくまで推測です)。
一度for文が回り終わってから、ボタンを押すことになります。
なので、ボタンが押されたときには、関数に渡しているiの値は、
for文が回ってからの値、すなわち、10(i=10になったら抜けるようになっているので)となり、
常に10が関数に渡されている、という事のようです。

なら、これはどうでしょうか。
function setBtn(){
for( i = 0; i < 10; i++){
this["btn"+i].onPress = function(){ mc_txt.text = this;}
}
}
setBtn();



これでは、押されたボタンのインスタンス名(レベルも含まれてます)が、表示されるようにしています。
これだと、for文で回しているにも関わらず、きちんと表示されています。

これは、先ほどの推測の通り、iを参照すると、for文が回ってしまった後のためおかしくなりますが、
thisだと、不変なため、正しく表示できているようです。

このことから、少しややこしい事をしている気もしますが、
以下のようにしてみます。

function setNum(mc){
var mcLength:Number = mc._name.length;
var mcNum:Number = mc._name.charAt(mcLength - 1);
testTxt(mcNum);
}
function setBtn(){
for( i = 0; i < 10; i++){
this["btn"+i].onPress = function(){ setNum(this);}
}
}
setBtn();



これは、インスタンス名は正しく取得できているところから、
そのインスタンス名の一番最後の文字から、ボタンの番号を抜き出してき、
それを関数に与えている、ということをしています。
これでとりあえず上手くいきました。

こうしてfor文で回すことによって、管理がしやすくなります。
以下のようにボタンを減らすことも容易です。
var max:Number = 5;
function setNum(mc){
var mcLength:Number = mc._name.length;
var mcNum:Number = mc._name.charAt(mcLength - 1);
testTxt(mcNum);
}
function setBtn(){
for( i = 0; i < max+1; i++){
this["btn"+i].onPress = function(){ setNum(this);}
}
}
setBtn();



ただし、付け焼刃的な対処のため、問題があります。

・ボタンのインスタンス名は、最後に連番となる数字をつけなければならない。
(今回のサンプルの場合だと、btn0 ~ btn9、となっています)
・数字は一桁までしか対応していない。
(10以上ボタンがある場合は対応できていません。少し改造すれば出来るようになるはずです。)

その他、諸所問題あると思います。

もっと簡単に出来るような気もしているんですけど、、、。
クラスとか使えば出来るんでしょうか。

Labels: ,

----------------------------------------------------------------------------------------------------

20080108

リンケージ設定


Flash IDE上において、ステージにライブラリにあるシンボル等をスクリプトで配置する場合、
あらかじめ、そのシンボルにリンケージ設定をしてやる必要があります。

方法は、ライブラリ上にあるシンボルを右クリックして、
リンケージプロパティを開き、ActionScriptに書き出し、にチェックを入れてやり、
識別子の名前をつけてやるだけです。

ただし、ここで気をつけなければならないのが、
リンケージ設定では、デフォルトで、
「最初のフレームに書き出し」
にチェックが入っているところです。

小規模なフラッシュや、スクリプトで書き出すシンボル等が少しなのであれば、
特に気にする必要はないのですが、
多くのシンボル、サウンドをこの方法で書き出すとなると注意が必要です。

というのも、swfのファイルサイズが大きくなると、必然的にローディングバー等のローディング処理が必要になります。
ですが、スクリプトで最初のフレームに書き出し処理をさせていると、
このローディングバー自体をロードする前に、これらのシンボルやサウンドの読み込み処理を開始してしまいますので、
ローディングバーが表示された段階では、すでに全体の何パーセントかが読み込まれてしまっていますので、
途中からのローディング処理に見えてしまうわけです。
(ローディングバーが表示されるまでは何も起こってないように見える)

では、どうすればいいのか、といいますと、
ローディングバーを1フレーム目に置いているのであれば、それ以降(2フレーム目以降)に書き出すようにしてやる必要があります。

まず、リンケージプロパティで、「最初のフレームに書き出し」のチェックをはずしてやります。
しかし、何フレーム目に書き出すかの設定はそのプロパティ内にはありません。
これは、設定で書くのではなくて、実際に書き出したいフレームのステージ上に、
そのシンボルを配置してしまえばいいのです。
こうすることによって、その配置したフレームに書き出しが行われます。
(当然、スクリプトで読み込み処理を行っているフレームよりも後ろに書き出してはいけません)
シンボルの場合はこれで完了ですが、サウンドの場合はそのフレームに来た時に、
誤って鳴ってしまわないように、フレームのプロパティの「同期」を、「停止」にしておきましょう。

参考サイト -
Macromedia Flash非公式テクニカルノート - コンポーネントとActionScript 2.0クラスの書出しフレームを変更する
教えて!goo - しばらく真っ白な画面になってしまいます。
Flash CS3 ドキュメンテーション - ステージへのムービークリップシンボルの割り当て

Labels:

----------------------------------------------------------------------------------------------------

CrossDomain(1)


フラッシュで、異なるドメイン間の通信を行う場合、
クロスドメンの処理が必要になります。

Macromedia-デベロッパセンター - Macromedia Flash Player 7 におけるセキュリティの変更について
(中段くらいにある、「ポリシーファイルの基本」を参照)
Macromedia Flash非公式テクニカルノート - MovieClip.loadVariables

要するに、通信される側のサーバの最上層に、crossdomain.xml を設置する必要がある、とのことです。

実際にcrossdomain.xmlの中身は以下のようなもの。
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/
cross-domain-policy.dtd">
<!-- Policy file for http://www.mysite.com -->
<cross-domain-policy>
<allow-access-from domain="*.mysite.com" />
<allow-access-from domain="www.myothersite.com" />
</cross-domain-policy>


このようなファイルが置いてあるサーバであれば、他のサーバからアクセスが出来るようになります。

※ただし、このファイルを設置することにより、セキュリティ上の問題が発生することがあるようです。
gihyo.jp - ここが危ない!Web2.0のセキュリティ 第4回 Flash,JSONでのクロスドメインアクセス

このことを意識するのは、ほとんどの場合、APIなどの他社のサービスを使うときだと思います。

以前、とあるサイトのブログパーツを作ったときに、
先方のサーバにこのポリシーファイルを設置しなければならないのかと危惧しましたが、
結果的に必要ありませんでした。
その時の構成は、貼ってもらうブログには、指定のjavascriptを貼ってもらい、
そこからswfを読み込み、そのswf内から、データ通信を行うものでした。
なので、swfが置いてあるドメインと、データ通信を行うドメインは、同じ、ということで、
クロスドメインの問題は起こらなかった、という感じでした。
(たとえHTMLに貼っていても、swfから見た階層、となるようです)


FlickrのAPIを使用して、プライベートでコンテンツを作成した時に、
この問題に行き当たりました。

Flickrにはcrossdomain.xmlは設置されています。
http://api.flickr.com/crossdomain.xml

ただし、ここで注意しなければいけないのが、
api.flickr.com
にはあるのであって、
www.flickr.com
にはcrossdomainファイルはない、ということです。
(セキュリティ上の問題かと思います。)

なので、flickrのAPIからデータを読み込む時には、このドメインに合わせないといけない、という事です。
ここで上手いこといかなくて、かなり悩みました、、。
(この両者のドメインによるデータ等の違いは、、わかりません)

どうしても、www.flickr.comを使いたい(アップロードさせる、など)などの、
crossdomain.xmlが設置されていないAPIなどのサービスをFlashで使用したい場合は、
間にPHPなどのプログラムを挟むことによって解決できるようです。
DEV.CONVEXSTYLE.NET - Flickr の新着 RSS 読み込み時の crossdomain 問題回避方法

PHPも要勉強、です。

Flickr APIを利用して作成した自作コンテンツにもリンクを貼っておきます。
Mr.littleBIG - 年賀状ジェネレータ

Labels:

----------------------------------------------------------------------------------------------------

20080107

TextField(1)


TextFieldについて。

入力テキストフィールドで入力された数字をそのまま足してしまうと、
数字として認識されず、文字列として認識されてしまいます。

なので、その場合は一度、数字に変換してやってから、
足すなどの計算をしてやる必要があります。

例)
1.数字に変換をしなかった場合。


2.数字への変換を行った場合。


ソース
1.数字に変換をしなかった場合
a_txt.maxChars = 1;
b_txt.maxChars = 2;

a_txt.restrict = "1-9";
b_txt.restrict = "0-9";

function calculation(){
a = a_txt.text;
b = b_txt.text;
var sum:Number = a+b;
sum_txt.text = sum;
}

sum_btn.onPress = function(){
calculation();
}

2.数字への変換を行った場合
a_txt.maxChars = 1;
b_txt.maxChars = 2;

a_txt.restrict = "1-9";
b_txt.restrict = "0-9";

function calculation(){
var a:Number = Number(a_txt.text);
var b:Number = Number(b_txt.text);
var sum:Number = a+b;
sum_txt.text = sum;
}

sum_btn.onPress = function(){
calculation();
}


変更している箇所は太字の部分のみ、です。

ようするに、数字であれば、
Number(~)
で、数字に変換できる、というわけです。

教えて!goo - アクションスクリプトで、足し算、引き算をするには?

ちなみに、この例では、数字のみを、入力、
更に、左の入力ボックスでは1桁、右では2桁、のみの入力しかできないようにしています。

この箇所です。
a_txt.maxChars = 1;
b_txt.maxChars = 2;

a_txt.restrict = "1-9";
b_txt.restrict = "0-9";


maxCharsで、入力文字数を制限、
(文字数なので、半角でも全角でも1文字、と判定する、、と思います。※未実証)
restrictで、入力文字を制限しています。

flair4 blog - Flashのテキストフィールドで文字入力を制限する

※ただし、背景色を透明にしてしまうと、WinのIEでは日本語入力が効かなくなるそうです。
fl0260 - wmode を transparent に設定した際の注意点
Flash-JP.COM - テキスト入力textfieldにIE6で日本語入力は×ですか?

これらの応用、とまではいきませんが、とある案件で、
とある日付までの日数のカウントダウン、
を作ったので、それをちょっと改造して、
入力された日付までの日数を表示するものを作ってみました。
(今年(2008年)は閏年なので、今年限定です、、。
さらに、今の日付よりも前の日付を入力すると、0日、と表示されるようにしました。)



ソースを書いておきます。
//現在の日にちを取得
var dateObj:Object = new Date;
var mm:Number = dateObj.getMonth() + 1;
var dd:Number = dateObj.getDate();

//日にちのセット
var m:Array = [31,29,31,30,31,30,31,31,30,31,30,31];

//トータル日にち用
var totalDay:Number = 0;

function calculation(){
//入力された日にちを数字に変換
var month:Number = Number(month_txt.text);
var day:Number = Number(day_txt.text);
//12月分ループ
for ( i = 0 ; i < 12 ; i++){
if ( month < mm){ //入力月が前月
totalDay = 0;
} else if ( month == mm){ //入力月が今月
if ( day <= dd){ //入力日が前日もしくは当日
totalDay = 0;
} else { //入力日までの日数を入れる
totalDay = day-dd;
}
} else{
if ( (i+1) < mm){ //i+1の値が今月より前の月

} else if( (i+1) == mm){//i+1の値が今月
totalDay += ( m[i] - dd);
} else{//i+1の値が今月以降
if ( (i+1) < month){
totalDay += m[i];
} else if ( (i+1) == month){
totalDay += day;
} else{
}
}
}
}
total_txt.text = totalDay;
}

sum_btn.onPress = function(){
totalDay = 0;
calculation();
}


もっと簡単に作れるかと思いきや、作ってみると思ったより長くなりました、、。

forループで、1~12月までまわして、それぞれの条件に合った日数を、
totalDayに足していっているのですが、
その条件分岐がちょっとややこしくなってます。

解説してみます。
(入力された月→month
入力された日→day
現在の月→mm
現在の日→dd
ループ中のi+1→I
と、します。)
1.monthがmm以前
2.monthがmmと同一
3.monthがmm以降
3の時のみ、Iを使った判定を行う。以下は、3の中の処理。
4.Iがmm以前
5.Iがmmと同一
6.Iがmm以降
6の中で、さらに以下を判定
7.Iがmonth以前
8.Iがmonthと同一
9.Iがmonth以降

と、なります。(書いてて自分でも混乱しそう、、)

それぞれの時にtotalDayに何を足していくかと言うと、、
1.0日とします。
2.日付の処理を行う。
3.-
4.何もしない
5.monthからmmを引いた値(今月の残り日数)を足す
6.-
7.それぞれの月の日数を足す
8.ddを足す
9.何もしない

2の日付の処理とは、月でやった、1~3の処理と同じ事を、
日付で行います。

これによって、入力された日付までの日数が表示される、はず、です。
(バグがあっても保障は致しません、、)


ちなみに、これに、年、を付加しようとなると、万年カレンダーの考え方が必要になります。

ですが、これは結構やっかいそうなので、
(昔からあるプログラムの練習問題みたいな感じのようですが、、)
参考リンクだけ、、。

参考:
Programのプ - 万年カレンダー解説
The page 31. - 論文:万年カレンダーを作る(上)

たぶん、日数計算だけなら、ユリウス通日、とか言うものの考え方を使えば簡単そう、、。

また万年カレンダーを作ったらここに解説します。

Labels: ,

----------------------------------------------------------------------------------------------------