swfコンテンツを埋め込むテスト
swfobject.jsを使って、Flashコンテンツをblog内に埋め込むテスト。
現状では、Flashを埋め込むにはswfobject.js(JavaScript)を使ってやるのが一般的なようだ。
こんな具合。
現状では、Flashを埋め込むにはswfobject.js(JavaScript)を使ってやるのが一般的なようだ。
ここにflashコンテンツが埋め込まれているはずなんだが...
こんな具合。
スポンサーサイト
PlaceEngine ActionScript APIを非対応版PEクライアントで使う
公開しているAPIを使ってくれている方がいらっしゃるようなので、久しぶりに追加コメントなどを。
このサイトで公開しているPlaceEngine ActionScript APIは、ローカルにインストールするPEクライアントについて、いまのところはクウジットから未公開の「crossdomain対応版クライアント」を使用することが前提になっています。
ですが、そうでない普通に公開されているPEクライアントであっても、Flash(Flex)コンテンツをデバッグ動作させるならうまく動くはずです。残念ながらwebサイトにuploadしてそれを読み込んで実行させる(いわゆる普通のflash動作)ではダメです。
私のところでは、Flex Builder環境下でデバッグで実行すれば、動いています。
ちなみに、Macでです。Windowsでも同様のはず(今は検証してませんが、APIを公開した時点では動くことを確認しました)。
まあ、それにどれだけ意味があるか、ってのはまた別の問題ですが...。
いずれにせよ、クウジットにまた連絡とってみようかな...。
このサイトで公開しているPlaceEngine ActionScript APIは、ローカルにインストールするPEクライアントについて、いまのところはクウジットから未公開の「crossdomain対応版クライアント」を使用することが前提になっています。
ですが、そうでない普通に公開されているPEクライアントであっても、Flash(Flex)コンテンツをデバッグ動作させるならうまく動くはずです。残念ながらwebサイトにuploadしてそれを読み込んで実行させる(いわゆる普通のflash動作)ではダメです。
私のところでは、Flex Builder環境下でデバッグで実行すれば、動いています。
ちなみに、Macでです。Windowsでも同様のはず(今は検証してませんが、APIを公開した時点では動くことを確認しました)。
まあ、それにどれだけ意味があるか、ってのはまた別の問題ですが...。
いずれにせよ、クウジットにまた連絡とってみようかな...。
PlaceEngine ActionScript APIの使い方
先に公開したPlaceEngine ActionScript APIの使い方コード。
Google Maps API for FlashとPlaceEngine APIを使って、現在位置を取得してそのエリアの地図を表示します。PlaceEngineサイトのAPI (Sample2)とほぼ同じ内容です。
動作例はこちら。
正しく動かすにはPlaceEngineクライアントのFlash対応版(未公開)が必要です。
以下、簡単にコードの解説などを。以下はごく基本的なところだけなので、細かい部分はソースコード全体や、ライブラリ側のコードを参照してください。ActionScriptがわかる人なら難しくないはずです。
まず、PlaceEngine APIを使うように宣言して、
statusLabel→APIからのメッセージの表示先。
appk→アプリケーションキー。
onFindClient→pingClient()を呼んでPEクライアントが存在したときのコールバック先。
onGetLocation→getLocation()を呼んで位置が取得できたときのコールバック先。
onMessage→APIでメッセージ出力がある際のコールバック先。
false→デバッグフラグ、trueでデバッグモード、省略可能。
この例はサンプルなので全部指定してますが、通常は使わないコールバック関数はnull指定でOK(省略は出来ない)。なので一般的にはこんな具合になろうかと。
それから、位置登録ボタンが押された場合は、
画面の作りはこんな感じで。PlaceEngineの推奨構成があるのでそれに準拠してます。
以下、コードの全文。ダウンロードはこちら。txtをmxmlに変更して使ってください。
Google Maps API for FlashとPlaceEngine APIを使って、現在位置を取得してそのエリアの地図を表示します。PlaceEngineサイトのAPI (Sample2)とほぼ同じ内容です。
動作例はこちら。
正しく動かすにはPlaceEngineクライアントのFlash対応版(未公開)が必要です。
以下、簡単にコードの解説などを。以下はごく基本的なところだけなので、細かい部分はソースコード全体や、ライブラリ側のコードを参照してください。ActionScriptがわかる人なら難しくないはずです。
まず、PlaceEngine APIを使うように宣言して、
import PlaceEngineAPI.PlaceEngineAPI;コード内の適当なところで、PlaceEnginAPIの実体を定義します。
//PlaceEngineの実体を生成引数は順に、
pe = new PlaceEngineAPI(statusLabel, appk, onFindClient, onGetLocation, onMessage, false);
statusLabel→APIからのメッセージの表示先。
appk→アプリケーションキー。
onFindClient→pingClient()を呼んでPEクライアントが存在したときのコールバック先。
onGetLocation→getLocation()を呼んで位置が取得できたときのコールバック先。
onMessage→APIでメッセージ出力がある際のコールバック先。
false→デバッグフラグ、trueでデバッグモード、省略可能。
この例はサンプルなので全部指定してますが、通常は使わないコールバック関数はnull指定でOK(省略は出来ない)。なので一般的にはこんな具合になろうかと。
pe = new PlaceEngineAPI(statusLabel, appk, null, onGetLocation, null);で、使えるように準備したところで、ボタンが押されるなど適当なトリガーで位置取得を開始します。
//位置を取得位置が取れると、上記で設定したコールバックメソッドが呼び出されます。
pe.getLocation();
//位置が取得できたらxyに経度緯度が入ってくるので、あとはそれをGoogleMapsAPIに食わせるなり何なりと。rは電波捕捉数兼エラーコードなので、0以上であることを確認しておく。infoには各種情報が連想配列になって入っているので必要に応じて使えます。
private function onGetLocation(x:Number, y:Number, r:int, info:Object):void{
if(r > 0){
map.panTo(new LatLng(x, y));
map.addOverlay(new Marker(new LatLng(x, y)));
}
}
それから、位置登録ボタンが押された場合は、
//登録用のインタフェースをたたくという具合に、登録用APIを呼びます。引数mapを指定してますが、指定しなくてもOK。
pe.registerLocation(map);
画面の作りはこんな感じで。PlaceEngineの推奨構成があるのでそれに準拠してます。
<mx:Panel title="PlaceEngine API Flash version. Ver.20080726" width="100%" height="100%" layout="absolute">
<mx:UIComponent id="mapContainer"
initialize="startMap(event);"
resize="resizeMap(event)"
right="0" left="0" bottom="78" top="30"/>
<mx:TextArea id="messageArea" right="0" left="0" bottom="0" height="70" wordWrap="true" verticalScrollPolicy="auto"/>
<mx:Button icon="@Embed('asset/wide_bt2.png')" width="102" height="22" id="registerButton"
click="registerButtonClick(event)" enabled="true"
useHandCursor="true" buttonMode="true" mouseChildren="false" left="5" top="5"/>
<mx:Button icon="@Embed('asset/wide_bt1.png')" width="102" height="22" id="getLocationButton"
click="getLocationButtonClick(event)" enabled="true"
useHandCursor="true" buttonMode="true" mouseChildren="false" top="5" left="115"/>
<mx:Image id="peLogo" source="@Embed('asset/logo_wh.gif')"
click="navigateToURL(new URLRequest('http://www.placeengine.com'))"
useHandCursor="true" buttonMode="true" mouseChildren="false" top="5" right="5"/>
<mx:Label id="statusLabel" top="7" left="220" right="125" text="PlaceEngineをインストールすると現在位置取得機能が使えるようになります"/>
</mx:Panel>
以下、コードの全文。ダウンロードはこちら。txtをmxmlに変更して使ってください。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%"
applicationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Text;
import flash.events.Event;
import PlaceEngineAPI.PlaceEngineAPI;
import com.google.maps.Map;
import com.google.maps.MapType;
import com.google.maps.MapEvent;
import com.google.maps.LatLng;
import com.google.maps.overlays.Marker;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.ZoomControl;
//PlaceEngineの実体
private var pe:PlaceEngineAPI;
//GoogleMapの実体
private var map:Map;
//マップ初期化OKかフラグ
private var isMapReady:Boolean = false;
//初期化コード
public function init():void{
//アプリケーションキー(自分で取得したものをここにセットする)
var appk:String = "ABCDEFG......";
//PlaceEngineの実体を生成
pe = new PlaceEngineAPI(statusLabel, appk, onFindClient, onGetLocation, onMessage, false);
//PEクライアントの有無を確認
pe.pingClient();
}
//GoogleMap初期化コード
public function startMap(event:Event):void {
//mapを生成
map = new Map();
//上手くgoogleと接続できてたら
if(map != null){
//キーをセット(自分で取得したものをここにセットする)
map.key="ABCDEFG....";
//イベントリスナ登録
map.addEventListener(MapEvent.MAP_READY, onMapReady);
//マップを登録
mapContainer.addChild(map);
}else{
trace("GoogleMapロードエラー");
}
}
//位置取得
private function getLocationButtonClick(event:Event):void{
//PEサイトへのリンクロゴを消す(ステータス表示のため)
if(peLogo.visible == true){
peLogo.visible = false;
}
//位置を取得
pe.getLocation();
}
//位置が取得できたら
private function onGetLocation(x:Number, y:Number, r:int, info:Object):void{
if(r > 0){
map.panTo(new LatLng(x, y));
map.addOverlay(new Marker(new LatLng(x, y)));
}
}
//位置登録
private function registerButtonClick(event:Event):void{
//PEサイトへのリンクロゴを消す(ステータス表示のため)
if(peLogo.visible == true){
peLogo.visible = false;
}
//登録用のインタフェースをたたく
pe.registerLocation(map);
}
//PEクライアントに対するping応答があったら
private function onFindClient(ver:String):void{
//messageArea.text += "\r" + "PlaceEngineクライアントのバージョンは " + ver + " です";
}
//メッセージが出力されると呼ばれるメソッド
private function onMessage(msg:String):void{
messageArea.text += "\r" + msg;
}
//リサイズされたとき
public function resizeMap(event:Event):void {
//マップの準備ができてないときにもこのイベントは発生するので
//準備ができているかをチェックする
if(isMapReady == true){
//マップがOKならリサイズする
map.setSize(new Point(mapContainer.width, mapContainer.height));
}
}
//マップの準備が出来たら呼ばれるイベントハンドラ
private function onMapReady(event:MapEvent):void {
//マップの準備ができたかフラグ
isMapReady = true;
//初期位置を皇居にセット
map.setCenter(new LatLng(35.684281,139.75163), 14, MapType.NORMAL_MAP_TYPE);
//各種部品を付ける
map.addControl(new ZoomControl());
map.addControl(new PositionControl());
map.addControl(new MapTypeControl());
//マップがOKならリサイズする
map.setSize(new Point(mapContainer.width, mapContainer.height));
}
]]>
</mx:Script>
<mx:Panel title="PlaceEngine API Flash version. Ver.20080726" width="100%" height="100%" layout="absolute">
<mx:UIComponent id="mapContainer"
initialize="startMap(event);"
resize="resizeMap(event)"
right="0" left="0" bottom="78" top="30"/>
<mx:TextArea id="messageArea" right="0" left="0" bottom="0" height="70" wordWrap="true" verticalScrollPolicy="auto"/>
<mx:Button icon="@Embed('asset/wide_bt2.png')" width="102" height="22" id="registerButton"
click="registerButtonClick(event)" enabled="true"
useHandCursor="true" buttonMode="true" mouseChildren="false" left="5" top="5"/>
<mx:Button icon="@Embed('asset/wide_bt1.png')" width="102" height="22" id="getLocationButton"
click="getLocationButtonClick(event)" enabled="true"
useHandCursor="true" buttonMode="true" mouseChildren="false" top="5" left="115"/>
<mx:Image id="peLogo" source="@Embed('asset/logo_wh.gif')"
click="navigateToURL(new URLRequest('http://www.placeengine.com'))"
useHandCursor="true" buttonMode="true" mouseChildren="false" top="5" right="5"/>
<mx:Label id="statusLabel" top="7" left="220" right="125" text="PlaceEngineをインストールすると現在位置取得機能が使えるようになります"/>
</mx:Panel>
</mx:Application>
PlaceEngine ActionScript API公開
PlaceEngineのAPIをFlex(ActionScript)から利用するためのライブラリを公開します。
現状では、crossdomain問題があるため、Flex(Flash)からPlaceEngineのAPIを叩いて位置測定などのサービスを利用することはできません。(デバッグモードでは動くけど。)
使えるようになるにはPlaceEngineクライアントとサーバの対応が必要で、実は現在、クウジットに対応をお願いしています。(いろいろありがとうございます。>クウジットの皆様)
このライブラリは、その対応をお願いする過程で私がテストのために作っていたコードを、それらしい形式にまとめたものです。コードはクウジットにも提供してありますが、こちらでも公開してもいいかなと。(ちなみに私はクウジットのまわしものではありませんw)
ライブラリは、一部ActionScriptに特有なところを除くと、PlaceEngine JavaScript APIとほとんど同じようにインタフェースを作ってありますので、そちらのドキュメントを参照すれば概ね同じように使えるはずです。
PlaceEngine側のFlex(Flash)対応がそう遠くないうちになされるだろう、という期待のもとに、それに備えてライブラリとして公開します。皆さんどんどん使ってください。
#なお、コードについてもっといい書き方があるよ、って場合にはぜひ教えてください。
ソースコードはこちら。PlaceEngine ActionScript APIライブラリ (拡張子を.txtから.asにして使ってください。)
以下全文です。
現状では、crossdomain問題があるため、Flex(Flash)からPlaceEngineのAPIを叩いて位置測定などのサービスを利用することはできません。(デバッグモードでは動くけど。)
使えるようになるにはPlaceEngineクライアントとサーバの対応が必要で、実は現在、クウジットに対応をお願いしています。(いろいろありがとうございます。>クウジットの皆様)
このライブラリは、その対応をお願いする過程で私がテストのために作っていたコードを、それらしい形式にまとめたものです。コードはクウジットにも提供してありますが、こちらでも公開してもいいかなと。(ちなみに私はクウジットのまわしものではありませんw)
ライブラリは、一部ActionScriptに特有なところを除くと、PlaceEngine JavaScript APIとほとんど同じようにインタフェースを作ってありますので、そちらのドキュメントを参照すれば概ね同じように使えるはずです。
PlaceEngine側のFlex(Flash)対応がそう遠くないうちになされるだろう、という期待のもとに、それに備えてライブラリとして公開します。皆さんどんどん使ってください。
#なお、コードについてもっといい書き方があるよ、って場合にはぜひ教えてください。
ソースコードはこちら。PlaceEngine ActionScript APIライブラリ (拡張子を.txtから.asにして使ってください。)
以下全文です。
package PlaceEngineAPI
{
import com.google.maps.LatLng;
import com.google.maps.Map;
import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.system.Security;
import mx.controls.Label;
public class PlaceEngineAPI
{
//ラベルオブジェクト(ステータス表示用)
private var labelObject:Label;
//アプリケーションキー
private var appk:String;
private var findClientFunc:Function;
private var getLocationFunc:Function;
private var messageFunc:Function;
private var debugMode:Boolean;
//タイムスタンプ
private var timeStamp:Date;
//このライブラリのバージョン
private const VERSION:String = "20080726";
//コンストラクタ
public function PlaceEngineAPI(label:Label, key:String,
findCliFunc:Function=null, getLocFunc:Function=null, mesFunc:Function=null,
debug:Boolean=false)
{
//引数内容をローカル変数にコピー
labelObject = label;
appk = key;
findClientFunc = findCliFunc;
getLocationFunc = getLocFunc;
messageFunc = mesFunc;
debugMode = debug;
}
//PEクライアントの有無を確認する
public function pingClient(str:String=null):void{
//引数に文字列が指定されていたら
if(str != null){
//文字列を出力
printMsg(str);
}
//クライアントが存在しているかを確認
timeStamp = new Date();
var URL:String = "http://localhost:5448/ackjs?t=";
URL += timeStamp.milliseconds;
var request:URLRequest = new URLRequest(URL);
var loader:URLLoader = new URLLoader();
setListeners(loader, "Ack");
sendRequest(loader, request);
}
//PEクライアントに対するAckを投げて応答があったら呼ばれるイベントハンドラ
private function completeHanderAck(event:Event):void{
printMsg("PlaceEngineクライアントが見つかりました");
var response:URLLoader = URLLoader(event.target);
//冒頭の"ackRTAG(""と"");"を外す
var tmpString:String = String(response.data);
var ackRTAG:String = tmpString.substr(9, tmpString.length-13);
//コールバック関数を呼ぶ
if(findClientFunc != null){
findClientFunc.call(findClientFunc, ackRTAG);
}
}
//位置登録ページを開く
//public fnction registerLocation():void{
public function registerLocation(map:Map=null):void{
var optionStr:String = "";
//引数にGoogle MapのMapが指定されていたら
if(map != null){
var latlng:LatLng = map.getCenter();
optionStr = "&x=" + latlng.lng().toString();
optionStr += "&y=" + latlng.lat().toString();
optionStr += "&z=" + map.getZoom().toString();
}
//PlaceEngineの位置登録ページを開く
var url:URLRequest = new URLRequest("http://www.placeengine.com/map?regiloc=1" + optionStr);
navigateToURL(url);
}
public function getLocation():void{
printMsg("WiFi情報取得中...");
//タイムスタンプとして現在時刻を取得
timeStamp = new Date();
//URL文字列を作成
var URL:String = "http://localhost:5448/rtagjs?t=";
URL += timeStamp.milliseconds + "&appk=";
URL += appk;
var request:URLRequest = new URLRequest(URL);
var loader:URLLoader = new URLLoader();
//イベントハンドラをセット
setListeners(loader, "Client");
//実際にリクエストを発行
sendRequest(loader, request);
}
//イベントハンドラをセットする
private function setListeners(dispatcher:IEventDispatcher, type:String):void {
//電測と位置取得とAckでハンドラを切り替える処理
if(type == "Client"){
dispatcher.addEventListener(Event.COMPLETE, completeHandlerClient);
}else if(type == "Server"){
dispatcher.addEventListener(Event.COMPLETE, completeHandlerServer);
}else if(type == "Ack"){
dispatcher.addEventListener(Event.COMPLETE, completeHanderAck);
}
//共通で利用するハンドラ
dispatcher.addEventListener(Event.OPEN, openHandler);
dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
//HTTP Request送信用メソッド
private function sendRequest(loader:URLLoader, request:URLRequest):void{
try {
loader.load(request);
}catch(error:ArgumentError){
debugPrintMsg("An ArgumentError has occurred.");
}catch(error:SecurityError){
debugPrintMsg("A SecurityError has occurred.");
}
}
//GETに対する応答が取得できたら呼ばれるハンドラ(クライアント)
private function completeHandlerClient(event:Event):void{
printMsg("PlaceEngineサーバに問い合わせ中...");
var response:URLLoader = URLLoader(event.target);
//冒頭の"recvRTAG"と");"を外して、パラメータを分解
var recvRTAG:String = String(response.data);
var rtagArray:Array = recvRTAG.substr(9, recvRTAG.length-12).split(",");
//rtag, numapを取得
var tmpString:String = rtagArray[0];
var rtag:String = tmpString.substr(1, tmpString.length-2); //""を外す処理
var numap:int = rtagArray[1];
if(numap > 0){
//電測が正常に取得できている場合
//サーバアクセスに先立って、crossdomain.xmlの場所を指定
Security.loadPolicyFile("http://www.placeengine.com/api/crossdomain.xml");
//URL文字列を作成
var URL2:String = "http://www.placeengine.com/api/loc?t=";
URL2 += timeStamp.milliseconds + "&rtag=";
URL2 += rtag + "&appk=";
URL2 += appk + "&fmt=json";
var request2:URLRequest = new URLRequest(URL2);
var loader2:URLLoader = new URLLoader();
//イベントハンドラをセット
setListeners(loader2, "Server");
//実際にリクエストを発行
sendRequest(loader2, request2);
}else{
//電測でエラーの場合
debugPrintMsg("電測でエラー発生 numap= " + numap);
//callBack関数を呼ぶ
if(getLocationFunc != null){
getLocationFunc.call(getLocationFunc, 0, 0, numap, null);
}
}
}
//GETに対する応答が取得できたら呼ばれるハンドラ(サーバ)
private function completeHandlerServer(event:Event):void{
//返す値を初期化
var lat:Number = 0;
var lon:Number = 0;
var range:int = 0;
var info:Object = new Object();
//レスポンスを取り出す
var response2:URLLoader = URLLoader(event.target);
//取得文字列を解析する
var tmpMessage:String = String(response2.data);
var recvMessage:String = tmpMessage.substr(1, tmpMessage.length-3); //両側の[]を外す
var param:Array = recvMessage.split(",");
var param2:Array = recvMessage.split("{");
if((param.length >= 4) && (param2.length >= 2)){
lat = param[1];
lon = param[0];
range = param[2];
//正常取得できている時
if(range > 0){
//infoの最後の"}"をはずす
var tmpParam2:String = String(param2[1]);
var infoArray:Array = tmpParam2.substr(0, tmpParam2.length-2).split(","); //-2なのは}を外すため
//JSON形式を解析
for(var i:int=0; i<infoArray.length; i++){
//":"で前後に分割して
var tmpArray:Array = String(infoArray[i]).split(":");
var name:String = tmpArray[0].substr(1, tmpArray[0].length-2);
var value:String = tmpArray[1];
//連想配列に格納
info[name] = value;
}
printMsg(info["addr"].substr(1, info["addr"].length-2));
}else{
//取得できていない時
debugPrintMsg("getLoc Error occurred. " + String(param2[1]));
}
}
//callBack関数を呼ぶ
if(getLocationFunc != null){
getLocationFunc.call(getLocationFunc, lat, lon, range, info);
}
}
private function openHandler(event:Event):void {
debugPrintMsg("openHandler: " + event);
}
private function progressHandler(event:ProgressEvent):void {
debugPrintMsg("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
debugPrintMsg("securityErrorHandler: " + event);
}
private function httpStatusHandler(event:HTTPStatusEvent):void {
debugPrintMsg("httpStatusHandler: " + event);
}
private function ioErrorHandler(event:IOErrorEvent):void {
debugPrintMsg("ioErrorHandler: " + event);
}
//ラベルにメッセージを出力するサポートメソッド
private function printMsg(str:String):void{
if(labelObject != null) {
labelObject.text = str;
}
//onMessagコールバック関数が定義されている場合にはそちらにも出力
if(messageFunc != null){
messageFunc.call(messageFunc, str);
}
}
//デバッグ出力用
private function debugPrintMsg(str:String):void{
//デバッグフラグがtrueでかつmessageFuncが指定されているときのみ
if(debugMode && (messageFunc != null)){
messageFunc.call(messageFunc, str);
}
}
//バージョン応答機能
private function getLibVersion():String{
return(VERSION);
}
}
}
yahooのcrossdomain.xml
先のツールを使ってflashでyahoo.co.jpにアクセスして、crossdomain.xmlを取得してみた。
yahoo.co.jpのcrossdomain.xmlはこうだった。
adobeのサンプル通りみたいだな。
yahoo.co.jpのcrossdomain.xmlはこうだった。
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain ="*" />
</cross-domain-policy>
adobeのサンプル通りみたいだな。