原文 http://www.imququ.com/post/use-canvas-as-background-image.html
最近iCloud Web的Beta版換了UI,整體風格變得和iOS7一致了。首頁圖標下方漂浮着若干大小不一的泡泡,十分夢幻。大家可以訪問 beta.icloud.com 體驗下,如果覺得泡泡不夠多,還可以加上 crazyAwesome 參數讓泡泡變得更加瘋狂。
上面提到的泡泡效果,有許多種實現方案。本文要討論的是iCloud使用的Canvas繪制背景圖方案。這樣做的好處是,用代碼繪制背景圖,相比圖片更靈活,也更省流量。另外,不知道大家有沒留意到iCloud Web中的日歷圖標是根據當前日期和星期幾動態生成的,下面Demo中有這個圖標的實現。
canvas.toDataURL
大家知道,一般我們可以用圖片、SVG和顏色漸變來做為元素的背景圖(background-image屬性)。在Canvas中,可以通過 toDataURL() 方法,把圖像導出為 data類型的URL ,這個URL可以直接用做背景圖。下面有個簡單的例子:
<div style="width:200px;height:200px;" id="cloud">紅心是我的背景圖!</div> <canvas style="display:none;" id="can" width="200" height="200"></canvas> <script> (function() { var canvas = document.getElementById('can'), context; if(!canvas.getContext) { alert('你的瀏覽器不支持canvas!'); return; } context = canvas.getContext('2d'); context.fillStyle = 'red'; context.beginPath(); context.moveTo(75,40); context.bezierCurveTo(75,37,70,25,50,25); context.bezierCurveTo(20,25,20,62.5,20,62.5); context.bezierCurveTo(20,80,40,102,75,120); context.bezierCurveTo(110,102,130,80,130,62.5); context.bezierCurveTo(130,62.5,130,25,100,25); context.bezierCurveTo(85,25,75,37,75,40); context.fill(); document.getElementById('cloud').style.backgroundImage = 'url("' + context.canvas.toDataURL() + '")'; })(); </script>
這是使用本方案實現的 iCloud日歷圖標 ,支持Canvas的瀏覽器都可以正常顯示。
用Canvas繪制背景圖,將Canvas強大的繪圖能力與靈活的CSS背景圖很好的結合起來,強大但不完美。例如多個元素使用同一個Canvas背景時,無論是分開設置背景圖,還是創建臨時Style,都很麻煩。如果想把一個Canvas動畫作為元素背景,需要不斷獲取DataURL再賦給元素,更加不方便。
有沒有更好的辦法可以把一個或多個html元素與Canvas綁定起來,在Canvas內容改變時自動更新html元素呢?答案是肯定的。
-webkit-canvas
對於上面的問題,Webkit提出了一個自己的實現方案:-webkit-canvas。Safari4+、Chrome4+的background-image都支持這個屬性值( caniuse ),可以方便的使用CSS Canvas作為元素的背景圖,類似這樣:
#icon1 { background-image: -webkit-canvas(identifier); }
區別於在Canvas元素上繪圖,-webkit-canvas方案需要用下面的方法獲取繪圖的Context:
var context = document.getCSSCanvasContext("2d", "identifier", width, height);
創建CSS Canvas時需要指定一個標識,用它的html元素在CSS中指定這個標識就可以了。瀏覽器會自動將CSS Canvas的改變同步到所有指定了這個標識的元素上,這樣就成功解決了上面提出的問題。
具體效果可以繼續 看我寫的Demo ,Webkit Only。這里還有一個使用-webkit-canvas將Canvas動畫作為背景圖的例子, 請自備梯子查看 。
-moz-element
Mozilla有個類似的方案,叫 -moz-element 。可以指定任何元素作為另外元素的背景圖(實際上,一個元素不能指定父元素作為自己的背景,為什么自己想),Firefox4+開始支持它作為background-image的屬性值。下面是它的用法:
<button id='elementID'>this is a element.</button> <div style='background-image:-moz-element(#elementID);width:300px;height:200px;'></div>
於是,上面的Demo在Firefox下可以改由-moz-element來實現了, 點擊查看 。由於本方案支持任何元素作為背景,所以 也可以這么玩 ,純CSS的有趣效果,Firefox Only。
最后
個人感覺Mozilla的方案略微誇張了點,相比之下Webkit的CSS Canvas更有可能成為標准。另外,iCloud對於不支持-webkit-canvas的瀏覽器使用的是DataURL方案,並沒有使用firefox的-moz-element,具體什么原因就不得而知了。