[AS]空っぽの文字列はNumberキャストで0
xmlの読み込みとかで、要素が空っぽだった場合の判定処理とかに。
var str:String; trace(0== Number(str))//出力:true
※5/17追記
上記の例だと要素に”0″とか”0000″とかが入ってたときもtrueになっちゃいます。
var str:String = "000" trace(0== Number(str))//出力:trueTweet
xmlの読み込みとかで、要素が空っぽだった場合の判定処理とかに。
var str:String; trace(0== Number(str))//出力:true
※5/17追記
上記の例だと要素に”0″とか”0000″とかが入ってたときもtrueになっちゃいます。
var str:String = "000" trace(0== Number(str))//出力:trueTweet
Xmlを読み込む際には、URLにユニークな変数を追加して、かならず再読み込みをさせたほうがいいみたい。
基本のURLのままだと、変更しても再読み込みの際、キャッシュから読んで新たに読み込んでくれない。
URL(String)にユニークな変数を追加する関数
import flash.net.LocalConnection;
//基本のURL
var xml_str:String = "http://hoge.com/hoge.xml";
//基本のURLにユニークな変数を追加
xml_str = setNoCashURL(xml_str);
private function setNoCashURL(url_str):String {
//サーバーにあがってるか同かを調べるため
var lc:LocalConnection = new LocalConnection();
//現在のドメイン名を取得
var domain_str:String = lc.domain;
//ドメイン名がlocalhostの時はローカルでのテストなので変数はつけない。
//(変数がついてるとローカルではxmlが読みこまれないみたい)
if (domain_str != "localhost") {
//現在時刻を取得することでユニークな数値を取得
var noCash:Number = new Date().getTime();
//URLに追加できる形にして数値を文字列化
var noCash_str:String = "?nocash="+String(noCash);
} else {
noCash_str = "";
}
url_str += noCash_str;
//変数を追加した文字列を返す
return url_str;
}
Tweet
FLASHでブラウザのスクロールバーを最上部に戻す方法で、最初出来たと思いきや不完全だったのでメモ。
基本設定は以下の通り。
ステージサイズを500×1000くらいにしておく
インスタンス名:_mcのムービークリップをステージの下の方に配置。
まず最初のイマイチアプローチから
以下フレームアクション
//AS:フレームアクション
_mc.addEventListener(MouseEvent.CLICK , xClick);
function xClick (e):void {
var tf = new TextField();
addChild(tf);
tf.text = "リロードしてないよ";
navigateToURL(new URLRequest("#","_self"));
}
これだけで出来ました。
ジャンプ先を#にするとブラウザリロードせずにページの先頭にジャンプできました。
先頭にはリロードしてないよの文字が表示されます。
で、これでいいや、と思いきや・・・
winのSafari3ではブラウザリロードしてしまいテキストが表示されません。
WINのIE6,7、FF3はリロードされなかったんですがね。。。
(HTMLの解釈的にはSafariの方が正しいっぽいような気がしますが)
というわけで別のアプローチ。
jsでスクロールバーを制御する方法。
js自体のソースはこちらのブログを参考にしました。
※イージングでゆっくりページのトップに戻るような処理のjsです。
//JS:HTMLに埋め込むか、jsファイルとしてhtmlで読み込むか
function backToTop() {
var x1 = x2 = x3 = 0;
var y1 = y2 = y3 = 0;
if (document.documentElement) {
x1 = document.documentElement.scrollLeft || 0;
y1 = document.documentElement.scrollTop || 0;
}
if (document.body) {
x2 = document.body.scrollLeft || 0;
y2 = document.body.scrollTop || 0;
}
x3 = window.scrollX || 0;
y3 = window.scrollY || 0;
var x = Math.max(x1, Math.max(x2, x3));
var y = Math.max(y1, Math.max(y2, y3));
window.scrollTo(Math.floor(x / 2), Math.floor(y / 2));
if (x > 0 || y > 0) {
window.setTimeout("backToTop()", 25);
}
}
上記関数をhtmlに仕込んでおいて、Flash側には以下のように設定
//AS:フレームアクション
_mc.addEventListener(MouseEvent.CLICK , xClick);
// 呼びたいJSの関数名
var callJasFunction:String = "backToTop";
// JavaScriptの実行
function xClick (e):void {
var tf = new TextField();
addChild(tf);
tf.text = "リロードしてないよ";
ExternalInterface.call(callJasFunction)
}
これでOKなのですが、Htmlにjs仕込むのが面倒くさい。
できることならFLASHだけで完結できないか、と。
と思ったら、こんな書き方でもFLASH上でJSを実行できるらしい。
//AS:フレームアクション
_mc.addEventListener(MouseEvent.CLICK , xClick);
// 呼びたいJSの関数
var callJasFunction:String = "function backToTop() {var x1 = x2 = x3 = 0;var y1 = y2 = y3 = 0;if (document.documentElement) {x1 = document.documentElement.scrollLeft || 0;y1 = document.documentElement.scrollTop || 0;}if (document.body) {x2 = document.body.scrollLeft || 0;y2 = document.body.scrollTop || 0;}x3 = window.scrollX || 0;y3 = window.scrollY || 0;var x = Math.max(x1, Math.max(x2, x3));var y = Math.max(y1, Math.max(y2, y3));window.scrollTo(Math.floor(x / 2), Math.floor(y / 2));if (x > 0 || y > 0) {window.setTimeout('backToTop()', 25);}}";
// JavaScriptの実行
function xClick (e):void {
var tf = new TextField();
addChild(tf);
tf.text = "リロードしてないよ";
ExternalInterface.call(callJasFunction)
}
ようは、関数名のところに関数全部書いちゃってもOKみたい。
これなら、Html変更しなくていいから楽チンだ!
と思いきや、これだと不具合ありました・・・
jsの再帰処理的な部分が実行されず、最初の一回しか実行されてないっぽい。
↓ここの部分
//上述したJSの一部を抜粋
if (x > 0 || y > 0) {
window.setTimeout("backToTop()", 25);
}
でも最初の一回は実行されるので、一回でトップに戻るようなjsなら問題なくページの頭だしは可能。
jsをこれだけにすれば、とりあえずイージングなしの頭だしは可能でした。
//AS:フレームアクション
_mc.addEventListener(MouseEvent.CLICK , xClick);
// 呼びたいJSの関数
var callJasFunction:String = "function backToTop() {window.scrollTo(0, 0);}";
// JavaScriptの実行
function xClick (e):void {
var tf = new TextField();
addChild(tf);
tf.text = "リロードしてないよ";
ExternalInterface.call(callJasFunction)
}
※2009/5/12追記
以下の書き方で再帰処理も可能でした。
document.insertScriptなんてものを使えばよいのだね。
JSよくわかんね。
_mc.addEventListener(MouseEvent.CLICK , xClick);
// 呼びたいJSの関数名
var callJasFunction:String = "document.insertScript = function(){ backToTop = function() {var x1 = x2 = x3 = 0;var y1 = y2 = y3 = 0;if (document.documentElement) {x1 = document.documentElement.scrollLeft || 0;y1 = document.documentElement.scrollTop || 0;}if (document.body) {x2 = document.body.scrollLeft || 0;y2 = document.body.scrollTop || 0;}x3 = window.scrollX || 0;y3 = window.scrollY || 0;var x = Math.max(x1, Math.max(x2, x3));var y = Math.max(y1, Math.max(y2, y3));window.scrollTo(Math.floor(x / 2), Math.floor(y / 2));if (x > 0 || y > 0) {window.setTimeout('backToTop()', 25);}}}";
var method = " backToTop";
//上記関数を読み込み(この段階では、関数backToTopは実行されないみたい)
ExternalInterface.call(callJasFunction)
// JavaScriptの実行
function xClick (e):void {
//ここで初めて実行されるみたい。
ExternalInterface.call("backToTop")
}
Tweet
忘れるのでメモ
function shuffleArray(myArray:Array){
var i:Number = myArray.length;
while(i){
var randomNumber:Number = Math.floor(Math.random()*(i--));
var temp:Object = myArray[i];
myArray[i] = myArray[randomNumber];
myArray[randomNumber] = temp;
}
}
Tweet
いろいろググってみても「出来ない」という結論しか見当たらなかったのだけど、どうやらAS2を対象にした結論だったのか、AS3なら簡単にできるようす。
(csvに限らず、ファイルならなんでも保存OKな感じ)
ステージに_mcというインスタンス名をつけたMCを配置して、フレームアクションに
var file:FileReference = new FileReference();
//ステージに_mcというインスタンス名をつけたMCを配置
_mc.addEventListener(MouseEvent.CLICK , xClick);
function xClick (e:MouseEvent):void {
try{
//ダウンロードしたいファイルのURLをURLRequestする。
file.download(new URLRequest("http://393.bz/sam/data.csv"));
} catch(e:Error){
//エラー時の処理
trace("error");
}
}
Tweet
ローカルの時間(PCに設定されてる時計による)ではなく、正確な時間を取得したい場合。
ただFLASH単体では、UTC(GMTみたいなもの)の取得はできないようす。
なのでサーバーサイドのプログラムPHPを使ったら意外と簡単にできました。
↓PHPはこれだけ
<?php
//GMTを取得
$time09 = gmdate("D M d Y H:i:s", time()+9*60*60);
//ASでは、utc_timeというプロパティで扱える
echo "utc_time=".$time09
?>
FLASH側はこんな感じで、読み込みます。
以下、フレームアクション
//フレームアクション
//PHPファイルのURLを定義
var request:URLRequest = new URLRequest ( "get_utc.php" );
//送信方法をPOSTに
request.method = URLRequestMethod.POST;
//ローダーを作って、PHPを読み込み(実行)
var loader:URLLoader = new URLLoader (request);
loader.addEventListener(Event.COMPLETE, onComplete);
loader.load(request);
//PHP読み込み(実行)後の処理
function onComplete(event:Event):void {
//↓PHPからの戻り値を変数に格納
var vars:URLVariables = new URLVariables( event.target.data );
//UTCデータを格納するための変数
var utc:String;
//データがちゃんとあった場合は、
if (vars.utc_time!= undefined) {
//変数に、文字列を渡す
utc = vars.utc_time;
next(utc);
//ムービープレビューのときはローカルタイムを取得
} else {
var date:Date = new Date();
utc = date.toString();
next(utc);
tf.text = "↓ローカルタイムです";
}
}
//PHPから読み込んだ文字列を引数にしてDateインスタンスを作成で完了
function next(utc) {
var date:Date = new Date(utc);
tf2.text = String(date);
}
//結果表示用のテキストフィールド(2つ用意)
var tf:TextField = new TextField();
tf.autoSize ="left";
addChild(tf);
var tf2:TextField = new TextField();
tf2.autoSize ="left";
addChild(tf2);
tf2.y = 30;
ポイントはPHPから取得した文字列をそのままDateクラスのコンストラクタの引数に突っ込めば、その情報を持ったDateインスタンスが作れるところですかね。
(逆に言うと、PHPで取得する文字列は、Dateクラスで認識できる形にしてあげる必要があるってことかね)
ただこの場合の「UTCタイム」はサーバーの時計ってことになるのかな?
ってことは、サーバーの時計が狂ったらアウトってことなんだろうね。
フレームアクションでこんな感じ。
var xml:XML =
<sampleXML>
<test>まるいち</test>
<test>まるに</test>
<test>まるさん</test>
<test>まるよん</test>
<test>まるご</test>
</sampleXML>;
trace(xml);
var xmlArray:Array = new Array();
var sampleXMLList:XMLList = xml.test;
//配列にtest要素を突っ込む
for (var i:uint = 0; i< sampleXMLList.length(); i++) {
xmlArray.push(xml.test[i]);
}
//配列の中身を確認
for (i = 0; i < xmlArray.length; i++) {
trace("xmlArray その1 : "+xmlArray[i]);
}
//配列を空にする。
xmlArray = [];
//配列にtest要素を突っ込む
for each (var container:Object in xml.test) {
xmlArray.push(container);
}
//配列の中身を確認
for (i = 0; i < xmlArray.length; i++) {
trace("xmlArray その2 : "+xmlArray[i]);
}
プレビュー時の出力はこんな感じ
xmlArray その1 : まるいち
xmlArray その1 : まるに
xmlArray その1 : まるさん
xmlArray その1 : まるよん
xmlArray その1 : まるご
xmlArray その2 : まるいち
xmlArray その2 : まるに
xmlArray その2 : まるさん
xmlArray その2 : まるよん
xmlArray その2 : まるご
注意するのは
Arrayの中身を数えるのは、Array.length
XMLListの中身を数えるのは、XMLList.length();
微妙に違うところ。
あとfor each (in)分を使えば、データの数がわからなくとも、データがあるだけループさせられる。
Tweet読み込んだXMLをTextFieldに表示させるときに、
XML側では、こんな感じで書くとその中の改行がそのまま表示できる。
<?xml version="1.0" encoding="UTF-8"?> <sample> <description> <![CDATA[あかさなた はまやらわ]]> </description> </sample>
ただその際に改行コードの問題で、一回しか改行してないつもりでも2行で改行されてしまうときがある。
↓こうでてほしいのに
あかさなた
はまやらわ
↓こうなる
あかさなた
はまやらわ
Windowsの改行コードの問題なので、
xmlから読み込んだストリングの改行コードを変換してあげればOK
//xmlから読み込んだストリングの var strictDescription:String = xml.description[0]; //改行コードを\nに統一する。 strictDescription = strictDescription.replace(/\r\n/g, '\n');Tweet
ストリーミングした動画を拡大するときはVideoオブジェクトを直接操作したほうがいいっぽい。
たとえば、MovieClipクラスを拡張して、Videoを再生するクラスがあったとする。
package {
import flash.display.MovieClip;
import flash.media.Video;
import flash.net.NetConnection;
import flash.events.NetStatusEvent;
import flash.net.NetStream;
public class LoadMovie extends MovieClip {
private var ncUrl:String
private var nsUrl:String
private var nc:NetConnection;
private var video:Video;
public function LoadMovie(ncUrl:String, nsUrl:String, w:uint = 320, h:uint = 320 ) {
trace("FmsMain");
this.ncUrl = ncUrl;
this.nsUrl = nsUrl;
video = new Video();
video.width = w;
video.height = h;
initConnect();
}
function initConnect():void {
//ネットコネクションを作る
nc = new NetConnection();
nc.client = new Object();
//ネットコネクションの接続状態を調べるリスナー
nc.addEventListener(NetStatusEvent.NET_STATUS , onNcStatus);
//ネットコネクションを接続する。
nc.connect(ncUrl);
}
//ネットコネクションの状態でいろいろ出力される
private function onNcStatus(e:NetStatusEvent):void {
trace("onNcStatus : "+e.info.code);
switch (e.info.code) {
//もし無事に接続されたら、
case "NetConnection.Connect.Success":
initStream();
break;
case "NetConnection.Connect.Failed":
trace("onNcStatus : "+e.info.code);
break;
case "NetStream.Play.StreamNotFound":
trace("not Found");
break;
default :
break;
}
}
//ネットストリームの初期化処理
private function initStream():void {
//ネットコネクションを作る
var ns:NetStream = new NetStream(nc);
//ネットコネクションの接続状態を調べるリスナー
ns.addEventListener(NetStatusEvent.NET_STATUS, onNsStatus);
//読み込みの時間を設定
ns.bufferTime = 2;
//メタデータ取得用のオブジェクトを設定
ns.client = new Object();
//videoインスタンスを作成
video.attachNetStream(ns);
addChild(video);
ns.play(nsUrl);
}
private function onNsStatus(e:NetStatusEvent):void {
switch (e.info.code) {
//もし失敗したら
case "NetStream.Play.StreamNotFound":
trace("NetStream Not Found");
break;
default :
trace("onNsStatus : "+e.info.code);
}
}
}
}
このクラスを利用するときはフレームアクションで、
(ローカルにelevator.flvがあるのが前提)
var ncUrl:String = null var nsUrl:String = "elevator.flv" var fms2:LoadMovie = new LoadMovie(ncUrl,nsUrl); addChild(fms2);
この動画のサイズを変えたいときに
var ncUrl:String = null var nsUrl:String = "elevator.flv" var fms2:LoadMovie = new LoadMovie(ncUrl,nsUrl); addChild(fms2); fms2.width = 500; fms2.height = 500;
まあlこれでも拡大されるのは予想通り。
ただしFMSのflvを読んでる場合は拡大されるずに動画が非表示になる。
(音はなってるから再生はされてるようす)
//これだと動画がなぜか表示されない var ncUrl:String = "rtmp://hoge.moge" var nsUrl:String = "doke" var fms2:LoadMovie = new LoadMovie(ncUrl,nsUrl); addChild(fms2); fms2.width = 500; fms2.height = 500;
LoadMovieクラスには、引数w,hでvideoオブジェクトのwidth、heightを操作できるようにしてあるので、
//これなら動画の大きさを操作できる。 var ncUrl:String = "rtmp://hoge.moge" var nsUrl:String = "doke" w = 500; h = 500; var fms2:LoadMovie = new LoadMovie(ncUrl,nsUrl,w,h); addChild(fms2);
もちろんローカルのflvを再生するときもこのVideoオブジェクトを操作する方法でOK。
なので、つねにこっちの方法を使った方が安全っぽい。
※
上記の例でFMSから読み込んだ場合のLoadMovieオブジェクトのwidthとheightは、w,hをどんな値を設定しても0になるようだ。
(ローカルflvを読み込んだ場合は指定した数値となる)
//FMSの場合 var ncUrl:String = "rtmp://hoge.moge" var nsUrl:String = "doke" w = 500; h = 500; var fms2:LoadMovie = new LoadMovie(ncUrl,nsUrl,w,h); addChild(fms2); trace(fms2.width) //出力:0 trace(fms2.height) //出力:0
ローカルflvを読み込んだ場合
//ローカルFLVの場合 var ncUrl:String = null var nsUrl:String = "elevator.flv" w = 500; h = 500; var fms2:LoadMovie = new LoadMovie(ncUrl,nsUrl,w,h); addChild(fms2); trace(fms2.width) //出力:500 trace(fms2.height) //出力:500
FMSから読み込んだものは実体がないということなのかな?
TweetFMS:Flash Media Server
ローカルのflvのprogressive再生のときとFMSでの設定の違いをメモしとく
NetConnectionの設定で
ローカルflvの時は
//ローカルのflvを再生するとき var nc:NetConnection = new NetConnection(); nc.connect(null);
FMSのときは、
//FMSを使うとき
var nc:NetConnection = new NetConnection();
nc.connect("rtmp://hoge.moge.ore.dore");
nc.client = new Object();
FMSのときはnc.connectにURLを設定(flvファイルの手前のフォルダまで)
※上の例はURLが rtmp://hoge.moge.dore.flvだった場合
あと、nc.client、ローカルflvでは設定しなくていいけど、FMSのときは設定してあげないとエラーになる。
あとNetStreamの設定
ローカルflvのときは、
var ns:NetStream = new NetStream(nc);
ns.play("doke.flv")
FMSのときは
var ns:NetStream = new NetStream(nc);
ns.play("doke")
FMSのときは、.flvをつけると宜しくないようす。
情報追記:2011/02/22
http://memo.393.bz/archives/1480