blog.Ring.idv.tw

HTML5

HTML5 video autoplay on iOS

許多時候我們在使用iPhone/iPad瀏覽一些包含HTML5 video的網頁時,會發現為何網頁中的video都不會自動播放?而使用一般PC平臺上的瀏覽器卻又都能自動播放?

根據iOS-Specific Considerations的說明如下:

In Safari on iOS (for all devices, including iPad), where the user may be on a cellular network and be charged per data unit, 
preload and autoplay are disabled. No data is loaded until the user initiates it. This means the JavaScript play() and load() methods 
are also inactive until the user initiates playback, unless the play() or load() method is triggered by user action. 
In other words, a user-initiated Play button works, but an onLoad="play()" event does not.

簡單來說~ 其實主要是用來防止「以量計價」的行動網路費爆增~ 這考量的確沒錯! 但是為何不將此功能改為可選項開關呢?因為現階段有許多採用資費吃到飽方案或是用WiFi網路的客群,若能提供可選項開關或是像使用GPS定位一樣的作法,主動彈出一個confirm視窗來提示是否允許自動播放也不失為一種方式呀!

所以~ 現階段如果想在iPhone/iPad瀏覽器中播放video那就得透過使用者觸發才行... Orz 話雖如此,但其實還可以透過另一種方式來達到video自動播放,那就是透過UIWebView元件來達成,也就是說~ 如果你是採用PhoneGap開發的應用程式,那恭禧你~ 只需要對AppDelegate.m 原始碼加上下述設定:

theWebView.allowsInlineMediaPlayback = YES;
theWebView.mediaPlaybackRequiresUserAction = NO;

同時也需要針對你的video element加上「webkit-playsinline」attribute即可,如:

<video id="video" src="xxx.mp4" autoplay webkit-playsinline></video>

現在開啟你的App就能看到video自動播放!

不過iOS Safari針對Canvas的支援仍有些不足~ 所以上述HTML5 Canvas&Video: Big Buck Bunny範例就算移植到UIWebView仍然無法看到效果的~ 因為iOS Safari針對Canvas少了下述APIs的支援:

void drawImage(HTMLVideoElement image, double dx, double dy);
void drawImage(HTMLVideoElement image, double dx, double dy, double dw, double dh);
void drawImage(HTMLVideoElement image, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh);

如此就只能被迫將video轉成一張張image才能達到類似的效果了...

參考資源

UNSOLVED HTML5 VIDEO ISSUES ON IOS

iPad and iPhone html5 video autoplay

2012-01-04 10:41:59 | Add Comment

淺談Canvas - save/restore

CanvasHTML5規格中的一部份,它允許你可以用程式來繪製一些2D圖形或是點陣圖,通常也被拿來製作HTML5遊戲之用,而本文主要介紹Canvas API中最常被初學者混淆的一組函式,它們分別為:「save()」和「restore()」,簡單來說~ 「save()」主要是用來保存目前Canvas的狀態,例如:style, lineWidth, font等,透過「save()」函式的呼叫它會將目前Canvas的狀態「Push」到「Stack」之中,而「restore()」函式就是從「Stack」來「Pop」出上一個Canvas的狀態,讀到這邊如果您已經了解「save/restore」的話,那非常恭禧你已經掌握要領了,反之~ 如果仍然有所疑惑的話,請看下面的範例介紹:

實作範例

本文將透過兩種不同的方式來實作出上圖的範例,以方便理解為何需要「save/restore」函式,使用它有何好處?

範例1 - 不採用save/restore

範例1完整的程式碼如下:(筆者假設您已經有基本的Canvas概念,所以會跳過一些基本的解說)

<!DOCTYPE html>
<html><head><meta charset="utf-8"></head><body>
<canvas id="a_canvas" width="200" height="150"></canvas>
<script type="text/javascript">
  var canvas = document.getElementById("a_canvas");
  var ctx = canvas.getContext("2d");
  function drawRect(context, color) {
    context.fillStyle = color;
    context.fillRect(0, 0, 100, 30);
  }
  function rotateDeg(context, deg) {
    var rad = deg * Math.PI / 180;
    context.rotate(rad);
  }
  drawRect(ctx, "red");
  ctx.translate(100,30); 
  rotateDeg(ctx, 45);    
  drawRect(ctx, "blue");
  rotateDeg(ctx, 45);    
  ctx.translate(20, -100); 
  drawRect(ctx, "green");
</script>
</body></html>

P.S. 下述圖形的虛線都作為解說之用,並非繪製在Canvas上的線條

drawRect(ctx, "red");

透過自訂的「drawRect()」函式,然後在Canvas上繪製一個從座標點(0,0)的位置畫一個長為100px寬為30px的紅色矩形。

ctx.translate(100,30); 

將目前Canvas的基準點位置設為(100,30),如上圖所示。

P.S. Canvas基準點位置預設為左上角,和Flash座標系統一致。

rotateDeg(ctx, 45);
drawRect(ctx, "blue");

透過自訂的「rotateDeg()」函式將Canvas往順時針旋轉45度,並繪製一個藍色矩形。

rotateDeg(ctx, 45);

接著再進行一次「rotateDeg()」函式將Canvas再往順時針旋轉45度。(此時已旋轉90度)

ctx.translate(20, -100);

到這邊的程式碼就是重點了,理論上如果以基準點為(0,0)的位置來說,目前要設定的相對基準點位置就是位於(200,50)的位置,但是在沒有運用「save/restore」的方式之下,我們必須自己在腦海裡進行一下矩陣轉換,同時根據上一次的基準點位置(100,30)以重設目前基準點位置(20,-100),最後再透過「drawRect(ctx, "green");」繪製出綠色的矩形出來。

範例2 - 採用save/restore

範例2完整的程式碼如下:

<!DOCTYPE html>
<html><head><meta charset="utf-8"></head><body>
<canvas id="a_canvas" width="200" height="150"></canvas>
<script type="text/javascript">
  var canvas = document.getElementById("a_canvas");
  var ctx = canvas.getContext("2d");
  function drawRect(context, color) {
    context.fillStyle = color;
    context.fillRect(0, 0, 100, 30);
  }
  function rotateDeg(context, deg) {
    var rad = deg * Math.PI / 180;
    context.rotate(rad);
  }
  drawRect(ctx, "red");
  ctx.save();            
  ctx.translate(100,30); 
  rotateDeg(ctx, 45);    
  drawRect(ctx, "blue");
  ctx.restore();         
  ctx.translate(200,50); 
  rotateDeg(ctx, 90);    
  drawRect(ctx, "green");
</script>
</body></html>

drawRect(ctx, "red");
ctx.save();            

除了在Canvas上繪製一個紅色的矩形外,這邊還呼叫了「save()」函式,意指為將目前的基準點位置(0,0)狀態「Push」到「Stack」中,以方便待會取回。

ctx.translate(100,30); 
rotateDeg(ctx, 45);    
drawRect(ctx, "blue");

將目前Canvas的基準點位置設為(100,30),同時旋轉45度並繪製上一個藍色矩形。

ctx.restore(); 

這裡呼叫「restore()」函式的重點就是要將剛剛「Push」到「Stack」的Canvas狀態取回,也就是重設基準點位置回到(0,0),並忘掉「save()」和「restore()」之間所設定的Canvas狀態,如:translate()、rotate()。

ctx.translate(200,50); 
rotateDeg(ctx, 90);    
drawRect(ctx, "green");

最後再重設基準點位置為(200,50),並順時針旋轉90度,然後畫上綠色矩形即大功告成,到這邊可以發現端倪了嗎?假設我們不採用「save/restore」函式來輔助的話,我們需要去進行矩陣轉換,而這只是個小範例~ 如果更複雜的圖形那勢必會轉到頭昏眼花... Orz,而透過「save/restore」函式的輔助,不僅讓程式碼的可讀性大大地增加,而且維護上也較為容易些嚕。

參考資源

Understanding save() and restore() for the Canvas Context

2011-11-02 22:14:01 | Add Comment

Next Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: Ads :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment