[Flash][JavaScript] FB Connect 取得朋友個人檔案原吋照片傳回 Flash

Standard

需求是醬子:

Flash 中點選按鈕→

跑出小視窗,要求登入FB聯外通→

列出朋友照片列表→

點選朋友照片→將被選朋友的個人檔案原吋照片傳回母視窗的 Flash 影片中。

當然,可以用 Facebook 給 Flash 的 API 去做更直接,但我還沒研究過這塊,都在摸 PHP & JS 的 FB 方法,跟 Flash 還不大熟 Orz

回歸正題,我分成幾個部分來說:
1. FB Connect 聯外通 與 取得權限
2. FQL in JavaScript 取得朋友列表 & 取得原吋大圖
3. Flash 與 JavaScript 的溝通,變數傳回


  1. FB Connect 聯外通 與 取得權限

Facebook 的聯外通機制似乎有改,原本的方法取得權限似乎不行。

OK,先設定會用到的 script:

<div id="fb-root"></div> 
<script>
  window.fbAsyncInit = function () {
    FB.init({appId: '應用程式 ID', status: true, cookie: true, xfbml: true});

    // fetch the status on load
    FB.getLoginStatus(function (response) {
      getFriendlist(); // 這邊自訂一個 getFriendlist 方法,希望登入後就直接去跑朋友列表
    });
  };

  (function() {
    var e = document.createElement('script');
    e.type = 'text/javascript';
    e.src = document.location.protocol + '//connect.facebook.net/zh_TW/all.js';
    e.async = true;
    document.getElementById('fb-root').appendChild(e);
  }()); // 把聯外通需要的 js 檔放到 fb-root 這個 div 裡
</script>

接著來做登入登出的按鈕:

<span class="btn" id="fblogin" onclick="facebookLogin('user_photos,friends_photos,user_photo_video_tags,friends_photo_video_tags');">Connect with Facebook</span>
<span class="btn" id="fblogout" onclick="facebookLogout();" style="display: none;">Logout from Facebook</span> 

之所以自訂是因為原生的 FBML 聯外通按鈕,似乎登入後自動重整的屬性在 IE & Firefox 上會失效,Chrome 倒是可以,尚未細究,先用自己寫的吧。

這邊用到了 facebookLoginfacebookLogout 兩個方法,下面緊接著列出:

function facebookLogin(permissions) {
  FB.login(function () {
    window.location.reload();
  }, {
    perms: permissions
  });
}

function facebookLogout() {
  FB.logout(function () {
    window.location.reload();
  });
}

facebookLogin 方法我一併塞入了所需的權限(Permission),這邊就看您應用程式的需求啦。另外我希望登入後可以自動重整頁面,window.location.reload()

facebookLogout 登出方法很單純,就不多說了。

  1. FQL in JavaScript 取得朋友列表 & 取得原吋大圖

取得朋友列表 getFriendlist(),使用 FQL 方法去撈(uid 是 Facebook 的使用者索引號、pic_small 是使用者的個人檔案小圖),然後把這些圖塞到某個 div 裡面,本例是 idfriendlistdiv
然後每個圖上都加一個 onclick 屬性,去呼叫抓大圖回傳的 function。

function getFriendlist() {
  var fbLoaded = false;
  FB.getLoginStatus(function(response) {
    var usession = response.session;

    if (usession != null && !fbLoaded) {
      var uid = "" + usession.uid;

      fbLoaded = true;
      $("#fblogin").hide();
      $("#fblogout").show();

      var fql = "SELECT uid,pic_small FROM user WHERE uid IN ( SELECT uid2 FROM friend WHERE uid1='" + uid + "' )";

      FB.api({
        method: 'fql.query',
        query: fql
      }, function(result, fbex) {
        if (fbex != null) {
          $("#fblogin").show();
          $("#fblogout").hide();
          fbLoaded = false;
          return;
        }

        var target = $('#friendlist');
        target.html('');

        // 取得要顯示API回傳資料的區塊                
        for (i = 0, j = result.length; i < j; i++) {
          if (result[i].pic_small === null || result[i].pic_small === '') {
            result[i].pic_small = 'http://static.ak.fbcdn.net/pics/q_silhouette.gif';
          }

          var html = '';
          html = '<img src="' + result[i].pic_small + '" longdesc="' + result[i].pic_small + '" onclick="getPicBigURL(' + result[i].uid + ')" />';
          $(html).appendTo(target);
        }
      });
    }
  });
}

接著是取得大圖的方法:
一樣用 FQL 去撈,撈出 src_big (大圖的網址),然後傳回母視窗。
這邊用到了呼叫母視窗 JavaScript function 的方法 opener.callFlash() 是為了把變數傳進 Flash。

function getPicBigURL(uid) {
  FB.getLoginStatus(function (response) {
    var fql = "SELECT src_big FROM photo WHERE pid IN (SELECT cover_pid FROM album WHERE owner ='" + uid + "' AND type = 'profile')";

    FB.api({
      method: 'fql.query',
      query: fql
    }, function (result, fbex) {
      if (fbex != null) {
        return;
      }

      try {
        // $("#photo").attr("src",result[0]['src_big']);
        opener.callFlash(result[0]['src_big']);
        window.close();
      } catch(exception) {
        alert("無法取得這名使用者的圖片,權限問題?請選擇另一位吧 >_<"); 
        return;
      }
    });
  });
}
  1. Flash 與 JavaScript 的溝通,變數傳回

OK,這個就跟 FB 沒啥關係了。
上面兩點都是在 window.open 叫出來的子視窗中做的。

母視窗我擺了個 Flash,裡面的 ActionScript:

btn.addEventListener(MouseEvent.CLICK,function(){
  ExternalInterface.call("openConnect");                                
});

ExternalInterface.addCallback("flashHello", flashHello);
function flashHello(message:String):void{
  picurl.text = "url is:" + message;

  var imgloader:Loader= new Loader();
  imgloader.load(new URLRequest(message));
  imgloader.name = "xchild";

  if (pic.getChildByName("xchild") != null) {
    pic.removeChild(pic.getChildByName("xchild"));
  }

  pic.addChild(imgloader);
}

ExternalInterface.call() 是用來呼叫 HTML 頁面上的 JavaScript function。
本例是開一個新視窗:

function openConnect() {
  window.open("getfriend.htm", "getfriend", "width=600,height=400,status=no,location=no,status=no,menubar=no,toolbar=no,resizable=no,scrollbars=yes");
}

那怎麼從外部用 JavaScript 去控制 Flash 的內容呢?
就是 ExternalInterface.addCallback 方法囉,第一個變數擺 JavaScript function name,第二個擺 flash 內的 function name。
我希望變數傳進來之後,在文字框內顯示字串、然後將圖片 load 進來擺到 MovieClip 上。

JavaScript 我自訂了一個 callFlash function,也就是子視窗呼叫的 function:

function callFlash(url) {
  var obj = swfobject.getObjectById("FlashID");
  if (obj) {
    obj.flashHello(url);
  }
}

上面提到 ExternalInterface.addCallback 方法,要先指定好 Flash 物件名稱,然後 物件名稱.Function名稱(變數) 去使用。若有使用 swfobject 的話,直接照上面那樣就可以抓到元件了。

參考:http://pro.ctlok.com/2010/06/javascript-actionscript.html

大概就是降子。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *