隨筆-17  評(píng)論-64  文章-79  trackbacks-1
          寬帶、媒體、電影、圖像和聲音等技術(shù)的出現(xiàn)推動(dòng)了 Web 2.0 的發(fā)展。了解如何把多媒體與 PHP 和 Asynchronous JavaScript™ + XML(Ajax)結(jié)合起來(lái)創(chuàng)造令人耳目一新的體驗(yàn)。

          如果問哪一個(gè)網(wǎng)站最能代表 Web 應(yīng)用程序的新潮流,多數(shù)人會(huì)回答 YouTube。這個(gè)網(wǎng)站不僅僅積極接納新技術(shù)營(yíng)造出夢(mèng)幻效果,而且改變了我們對(duì)多媒體的看法,改變了我們和媒體的關(guān)系。許多故事在以傳統(tǒng)媒體渠道傳播之前就已經(jīng)出現(xiàn)在 YouTube 上了,當(dāng)它們不再流傳時(shí),YouTube 就會(huì)像全世界的一個(gè)巨大的 Tivo,記錄著曾經(jīng)發(fā)生的點(diǎn)點(diǎn)滴滴。

          媒體分享正在改變世界,而且從技術(shù)的觀點(diǎn)來(lái)說(shuō),這并不難做到。本文介紹如何在 Web 視頻托管應(yīng)用程序上增加一個(gè) Ajax 前端。

          簡(jiǎn)單的視頻選擇

          首先來(lái)看網(wǎng)站,網(wǎng)站上有一個(gè)電影列表可供選擇 — 一個(gè)不用改變頁(yè)面就能選擇不同電影的網(wǎng)站。頁(yè)面代碼如 清單 1 所示。


          清單 1. index.html
                      <html>
                      <head>
                      <script src="prototype.js"></script>
                      </head>
                      <body>
                      <div id="movieHost">
                      </div>
                      <div id="movieList">
                      </div>
                      <script>
                      function setMovie( url )
                      {
                      $('movieHost').innerHTML = '';
                      var elEmbed = document.createElement( 'embed' );
                      elEmbed.src = url;
                      $('movieHost').appendChild( elEmbed );
                      }
                      new Ajax.Request( 'movies.xml', {
                      method: 'get',
                      onSuccess: function( transport ) {
                      var movieTags = transport.responseXML.getElementsByTagName( 'movie' );
                      $('movieList').innerHTML = '';
                      var bFirst = true;
                      for( var b = 0; b < movieTags.length; b++ ) {
                      var url = movieTags[b].getAttribute('url');
                      var title = movieTags[b].getAttribute('title');
                      if ( bFirst )
                      {
                      setMovie( url );
                      bFirst = false;
                      }
                      var html = '<a href="javascript:void setMovie(\''+url+'\');">';
                      html += title+'</a><br/>';
                      $('movieList').innerHTML += html;
                      }
                      }
                      } );
                      </script>
                      </body>
                      </html>
                      

          該頁(yè)面使用 Prototype.js 這個(gè)很棒的 JavaScript 庫(kù)向 movies.xml 數(shù)據(jù)源發(fā)送 Ajax 請(qǐng)求。返回?cái)?shù)據(jù)后通過 getElementsByTagName() 方法查找所有電影標(biāo)簽。對(duì)每個(gè)電影標(biāo)簽,代碼檢索 URL 和標(biāo)題。如果檢索的標(biāo)簽是列表中的第一部電影,腳本立即開始放映這部電影。否則添加一個(gè) anchor 標(biāo)簽作為 movieList <div> 的電影選擇器。

          電影選擇器 anchor 調(diào)用 setMovie() 函數(shù)打開指定的電影。播放電影的方法很簡(jiǎn)單,首先將 movieHost <div> 標(biāo)簽置空,即刪除原來(lái)的電影。然后將內(nèi)容設(shè)置為 <embed> 標(biāo)簽,其 URL 由電影列表指定。

          <embed> 標(biāo)簽是在頁(yè)面中播放電影最簡(jiǎn)單的方法,但是存在跨瀏覽器的問題。另一種辦法是同時(shí)使用 <object><embed> 標(biāo)簽(還有一種辦法,即使用 Macromedia Flash Player:本文稍后 再討論)。

          這個(gè)簡(jiǎn)單的例子中,movies.xml 只是一個(gè)平面文件,包含一些我自己的家庭短片的引用。該文件如 清單 2 所示。


          清單 2. movies.xml
                      <movies>
                      <movie url="spider.mov" title="Spider" />
                      <movie url="swing.mov" title="Swing Set" />
                      <movie url="water.mov" title="Water Splash" />
                      </movies>
                      

          打開該頁(yè)面時(shí),顯示的結(jié)果如 圖 1 所示。


          圖 1. 簡(jiǎn)單的電影列表頁(yè)面
          簡(jiǎn)單的電影列表頁(yè)面

          最上方是一部由 <embed> 標(biāo)簽播放的電影,下面是其他影片列表。點(diǎn)擊其中的任何鏈接,正在播放的電影就變成所選擇的電影。

          顯然,這個(gè)系統(tǒng)不適合大型的視頻資料庫(kù),還需要對(duì)影片列表進(jìn)行某種搜索。





          回頁(yè)首


          可搜索的電影列表

          要添加搜索功能,必須添加一個(gè)搜索框,如 清單 3 所示。其中增加了搜索輸入字段 q


          清單 3. 添加搜索功能
                      <html>
                      <head>
                      <script src="prototype.js"></script>
                      </head>
                      <body>
                      <table><tr><td valign="top">
                      <input type="text" id="q" onkeyup="search()">
                      <div id="movieList">
                      </div>
                      </td><td valign="top">
                      <div id="movieHost">
                      </div>
                      </td>
                      </tr></table>
                      <script>
                      function setMovie( url )
                      {
                      $('movieHost').innerHTML = '';
                      var elEmbed = document.createElement( 'embed' );
                      elEmbed.src = url;
                      $('movieHost').appendChild( elEmbed );
                      }
                      function search()
                      {
                      new Ajax.Request( 'search.php?q='+escape($('q').value), {
                      method: 'get',
                      onSuccess: function( transport ) {
                      var movieTags = transport.responseXML.getElementsByTagName( 'movie' );
                      $('movieList').innerHTML = '';
                      var bFirst = true;
                      for( var b = 0; b < movieTags.length; b++ ) {
                      var url = movieTags[b].getAttribute('url');
                      var title = movieTags[b].getAttribute('title');
                      if ( bFirst )
                      {
                      setMovie( url );
                      bFirst = false;
                      }
                      var html = '<a href="javascript:void setMovie(\''+url+'\');">';
                      html += title+'</a><br/>';
                      $('movieList').innerHTML += html;
                      }
                      }
                      } );
                      }
                      </script>
                      </body>
                      </html>
                      

          在 key-up 事件中指定 search() 方法將被調(diào)用。search() 方法和 Ajax.Request 調(diào)用類似,除了向 search.php 頁(yè)面?zhèn)鬟f查詢字符串。search.php 腳本返回和原來(lái)相同的 XML 格式,因此不需要修改 XML 解析的代碼。

          我承認(rèn)對(duì)于自己的習(xí)慣來(lái)說(shuō),key-up 上的 search() 函數(shù)反映有點(diǎn)太快。理想情況下,系統(tǒng)應(yīng)該在執(zhí)行搜索之前等待一秒左右以便輸入完整的搜索文本,避免列表不停地閃爍。使用 window.setTimeout() 方法很容易實(shí)現(xiàn)這種行為。

          清單 4 顯示了經(jīng)過修改的 search.php 腳本。


          清單 4. search.php
                      <?php
                      header( 'content-type: text/xml' );
                      $movies = array();
                      $movies['spider.mov'] = 'Spider';
                      $movies['swing.mov'] = 'Swing Set';
                      $movies['water.mov'] = 'Water Splash';
                      ?>
                      <movies>
                      <?php
                      foreach( $movies as $k => $v ) {
                      if ( strlen( $_GET['q'] ) > 0 &&
                      preg_match( '/'.$_GET['q'].'/i', $v ) ) {
                      ?>
                      <movie url="<?php echo($k) ?>" title="<?php echo($v) ?>" />
                      <?php
                      } }
                      ?>
                      </movies>
                      

          腳本一開始建立了一個(gè)數(shù)組保存全部電影。為了簡(jiǎn)化起見,這里對(duì)電影進(jìn)行了硬編碼。實(shí)際應(yīng)用的時(shí)候這些元素很可能取自電影清單的數(shù)據(jù)庫(kù)。

          接下來(lái)的代碼遍歷列表,把搜索查詢的正則表達(dá)式應(yīng)用于每個(gè)電影的標(biāo)題。如果匹配則輸出包含 URL 和名稱的 <movie> 標(biāo)簽。

          打開頁(yè)面并輸入 s,將看到 圖 2 所示的頁(yè)面。


          圖 2. 簡(jiǎn)單的電影查詢頁(yè)面
          簡(jiǎn)單的電影查詢頁(yè)面

          如果按下 Delete 建并輸入 water,就會(huì)看到 圖 3 所示的頁(yè)面。


          圖 3. 搜索與 “water” 相關(guān)的電影的查詢頁(yè)面
          搜索與 “water” 相關(guān)的電影的查詢頁(yè)面

          雖然本文主要討論如何使用 Dynamic HTML(DHTML)和 Ajax 建立前端應(yīng)用程序,但視頻共享網(wǎng)站決不是這么簡(jiǎn)單。





          回頁(yè)首


          視頻分享基礎(chǔ)

          先暫時(shí)離開實(shí)踐問題討論一些更具理論性的東西,視頻共享中更加復(fù)雜的問題。涉及到三個(gè)主要問題:

          • 如何存儲(chǔ)和傳輸視頻
          • 如何處理不同的視頻格式
          • 如何從上傳文件中獲得縮略圖和視頻信息

          視頻存儲(chǔ)是一個(gè)實(shí)實(shí)在在的問題 — 特別是對(duì)于小應(yīng)用程序而言視頻文件非常大,需要大容量的硬盤空間來(lái)存儲(chǔ)。將其傳遞給客戶還面臨著帶寬的挑戰(zhàn)。可以自己購(gòu)買設(shè)備安裝到托管設(shè)施中。或者使用 Amazon S3 這樣的服務(wù),只需很低的價(jià)格就能上傳任何資料(數(shù)據(jù)庫(kù)備份、圖片、電影等等)到 Amazon 數(shù)據(jù)中心,以及提供給其他客戶。和建立數(shù)據(jù)中心的大量投資相比可以先考慮一下這些服務(wù)。

          下一個(gè)問題 — 視頻格式 — 提出了一個(gè)有趣的挑戰(zhàn)。存在多種視頻格式,沒有任何一種播放器能支持所有格式。事實(shí)上多數(shù)播放器只能處理自己挑選的視頻格式。為了方便用戶,也許最好以某種格式為標(biāo)準(zhǔn)然后將所有傳來(lái)的視頻都轉(zhuǎn)化成這種格式。有一種非常方便的工具,即命令行應(yīng)用程序 FFmpeg。它不僅能把一種視頻格式轉(zhuǎn)化成另一種,還能拾取畫面的快照從而為用戶提供視頻縮略圖。

          選擇何種視頻格式作為標(biāo)準(zhǔn)可能很麻煩。目前 Flash 視頻具有明顯的優(yōu)勢(shì),但是 Windows Media®,特別是隨著 Microsoft Silverlight(原來(lái)的 WPF/Everywhere)的發(fā)布,正在贏得越來(lái)越多的支持。FFmpeg 幾乎能將任何影片格式轉(zhuǎn)化成 Flash 視頻格式,這一點(diǎn)很吸引人。而且有一些免費(fèi)和開源的 Flash 播放器很容易嵌入到網(wǎng)站上。將這些播放器和上述代碼結(jié)合起來(lái)就能建立一個(gè)完整的、以 Ajax 為前端的端到端視頻分享解決方案。

          但 Web 上不僅僅有視頻,圖像共享也很重要。





          回頁(yè)首


          幻燈片放映

          清單 5 顯示了一個(gè)簡(jiǎn)單的基于 DHTML 的幻燈片,數(shù)據(jù)來(lái)自 XML 文件。


          清單 5. index.html
                      <html>
                      <head>
                      <script src="prototype.js"></script>
                      </head>
                      <body bgcolor="black">
                      <div style="text-align:center;">
                      <img id="imgItem" src="" style="display:none;"><br>
                      <div id="imgTitle" style="color:white;font-family:arial;font-size:24pt;">
                      </div>
                      </div>
                      <script>
                      var g_images = [];
                      var g_slideIndex = 0;
                      function showSlide()
                      {
                      $('imgTitle').hide();
                      $('imgItem').hide();
                      var height = 600;
                      var width = ( height / g_images[ g_slideIndex ].height ) *
                      g_images[ g_slideIndex ].width;
                      $('imgItem').src = g_images[ g_slideIndex ].src;
                      $('imgItem').width = width;
                      $('imgItem').height = height;
                      $('imgTitle').innerHTML = g_images[ g_slideIndex ].title;
                      $('imgTitle').show();
                      $('imgItem').show();
                      g_slideIndex++;
                      if ( g_slideIndex >= g_images.length )
                      g_slideIndex = 0;
                      }
                      new Ajax.Request( 'images.xml', {
                      method: 'get',
                      onSuccess: function( transport ) {
                      var imageTags = transport.responseXML.getElementsByTagName( 'image' );
                      for( var b = 0; b < imageTags.length; b++ ) {
                      g_images.push( {
                      src: imageTags[b].getAttribute('src'),
                      title: imageTags[b].getAttribute('title'),
                      width: imageTags[b].getAttribute('width'),
                      height: imageTags[b].getAttribute('height')
                      } );
                      }
                      showSlide();
                      window.setInterval( showSlide, 5000 );
                      }
                      } );
                      </script>
                      </body>
                      </html>
                      

          分享這篇文章……

          digg 提交到 Digg
          del.icio.us 發(fā)布到 del.icio.us

          上述代碼需要用到 Prototype.js JavaScript 庫(kù)。利用 Ajax.Request 對(duì)象獲得要顯示的圖片列表。然后解析返回的 XML 代碼,獲得圖片的 URL、寬、高和標(biāo)題。然后調(diào)用 showSlide() 函數(shù)得到幻燈片顯示效果。設(shè)置的計(jì)時(shí)器每五秒切換到下一張幻燈片。

          幻燈片放映通過包含當(dāng)前圖片的 <image> 標(biāo)簽和標(biāo)題 <div> 標(biāo)簽實(shí)現(xiàn)。所謂放映只不過是隱藏當(dāng)前的圖片和標(biāo)題,將圖片來(lái)源和標(biāo)題文本設(shè)置為新幻燈片的內(nèi)容并顯示。如果需要某種淡入淡出效果,建議使用 Scriptaculous 庫(kù)中的 Effects 類,它是構(gòu)建在 Prototype.js 上的。

          清單 6 顯示了數(shù)據(jù)圖像文件。


          清單 6. images.xml
                      <images>
                      <image src="images/megan1_875_700.jpg" title="Megan" width="875" height="700" />
                      <image src="images/oso1_875_700.jpg" title="Oso 1" width="875" height="700" />
                      <image src="images/oso2_873_700.jpg" title="Oso 2" width="873" height="700" />
                      </images>
                      

          這里雖然使用了硬編碼,但使用 PHP 腳本很容易生成 XML 代碼。幻燈片放映如 圖 4 所示。


          圖 4. 簡(jiǎn)單的幻燈片放映
          簡(jiǎn)單的幻燈片放映

          注意:我以前介紹過一個(gè)更加精細(xì)的幻燈片放映版本(要獲得相關(guān)鏈接,參見參考資料)。現(xiàn)在這個(gè)版本的區(qū)別在于使用了 Prototype.js 庫(kù),各幻燈片之間的切換更簡(jiǎn)單。





          回頁(yè)首


          結(jié)束語(yǔ)

          像 Flikr 和 YouTube 之類的網(wǎng)站僅僅顯示了 Web 上的多媒體應(yīng)用的巨大潛能的冰山一角。本文介紹了一些非常簡(jiǎn)便的視頻和圖片瀏覽的實(shí)現(xiàn),可用于您自己的項(xiàng)目。如果有效,請(qǐng)參加 developerWorks Ajax 論壇(參見 參考資料)告訴我您取得的成功。

          posted on 2007-11-25 11:58 飛鳥 閱讀(209) 評(píng)論(0)  編輯  收藏 所屬分類: AJAX
          主站蜘蛛池模板: 白水县| 高碑店市| 阜平县| 彭山县| 开阳县| 尚志市| 株洲市| 高州市| 仁布县| 额尔古纳市| 什邡市| 淮阳县| 泸溪县| 繁昌县| 青龙| 乡城县| 万州区| 仙桃市| 迁安市| 江门市| 新乐市| 广东省| 尚志市| 上杭县| 阿勒泰市| 柘荣县| 通山县| 乌兰县| 象山县| 江津市| 和政县| 闵行区| 浦城县| 鄄城县| 象山县| 长宁区| 舞钢市| 葫芦岛市| 新丰县| 宁安市| 乌兰察布市|