以前我在 SF 上回答過「html5 canvas繪製圖片模糊的問題」,可是多是因爲我給出的答案過於簡略,加上答案中的 demo 連接已經失效,不少人反映這種辦法並很差使。可是我在給出答案以前是在小米2 和 iPhone 上測試過的,沒有任何問題。下面我會一步一步地描述具體的步驟。html
假設咱們要在 canvas 中繪製一張 300 x 90
的圖片,而且要保證它在高清屏中不模糊。那麼咱們首先要準備一張 600 x 180
的圖片,處理太高清屏的同窗應該會有這方面的經驗。html5
OK,咱們先把問題重現一下,以便有一個更直觀的瞭解。下面是相關的代碼(爲了簡單起見,我把代碼都寫在了 HTML 文檔裏面):git
<!-- 經過 img 標籤引入圖片,以便繪製到 canvas 中 --> <img src="html5rocks.png" alt="" width="300" height="90"> <!-- canvas --> <canvas width="300" height="90"></canvas> <script> function init() { var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); ctx.drawImage(document.querySelector('img'), 0, 0, 300, 90); } window.onload = init; </script>
代碼很簡單,沒有作任何處理,具體的效果和完整的代碼能夠查看這個 DEMO,這個 demo 在高清屏的手機中會出現的問題:canvas 中的圖片變模糊了!。github
至於爲何會變模糊,這和瀏覽器處理 canvas 的方式有關,相關的文章能夠參考這篇 High DPI Canvas,這裏不做深刻介紹。web
其實,不僅是繪製圖片時會出現模糊的問題,正常狀況下,在高清屏的設備中,任何繪製在 canvas 中的圖形(包括文字)都會出現模糊的問題。上面這個 polyfill 就是爲了解決這個問題,可是它沒有處理圖片。canvas
將 init
函數修改爲下面這樣:segmentfault
function init() { var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); // polyfill 提供了這個方法用來獲取設備的 pixel ratio var getPixelRatio = function(context) { var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; return (window.devicePixelRatio || 1) / backingStore; }; var ratio = getPixelRatio(ctx); // 注意,這裏的 width 和 height 變成了 width * ratio 和 height * ratio ctx.drawImage(document.querySelector('img'), 0, 0, 300 * ratio, 90 * ratio); }
能夠點擊這裏查看完整的代碼和效果,在高清屏的設備中打開,看看 cavans 中的圖片是否完美顯示。瀏覽器
這個解決方案本質上和 @白一梓 的答案是同樣的:先放大 canvas,再用 CSS 將其限制回原始大小。app
若是你看了 polyfill 的代碼就會明白其中的原理了,這個 polyfill 的代碼十分簡短明瞭,它作了兩件事:一是將 canvas 的高和寬分別乘以 ratio 將其放大,而後又用 CSS 將高和寬限制成初始的大小;二是 hack canvas 中經常使用的函數,如:fillRect
, clearRect
, lineTo
, arc
等,將它們的參數都乘以 ratio,以方便咱們能夠像之前那樣使用這些方法,而不用在傳參的時候手動乘以 ratio。函數