近期的工做中,是繼 canvas 寬高問題 以後碰到的第二個問題。javascript
在 PC 瀏覽器上顯示時,沒有發現明顯的模糊,還能夠接受。但在手機上就會有明顯的模糊。這是示例,掃描訪問二維碼以下。css
示例中,用 css 控制 canvas 的寬高,裏面的圖片展現效果不一致。查詢資料,在 stackoverflow 中發現一樣的問題,經過實際測試發現:html
width
和 height
,決定了多少像素能夠顯示在畫布上,若是不設置,width 默認值是 300,height 默認值是 150。width
和 height
,是指在屏幕上元素顯示的大小,若是沒有對 canvas 進行 css 設置,則會採用 canvas 的默認大小。width
和 height
,當在畫布裏面使用 drawImage
設置圖片寬高時,顯示的寬高值會根據必定比例進行轉換。例如在上面例子中,設置的圖片是寬 300 高 90, canvas 默認寬高渲染像素 300 和 150,(css 高度/canvas 自身屬性高度) * drawImage 設置的高度 = (90/150)* 90 = 54。在規範裏面還真沒看出來這些。html5
在 stackoverflow 上也找到相關的問題,在回答中有相關介紹的文章HTML5 Rocks。緣由是 canvas 繪製時獨立於設備像素比(devicePixelRatio)。受到 devicePixelRatio 影響,在高清顯示屏上,一個邏輯像素對應多個實際的設備物理像素。例如在 devicePixelRatio 爲 2 的設備上,css 設置的 100px,意味着設備上要填充 200px 物理像素,那麼當 canvas 繪製 100px 的區域時,實際是想在設備填充 100px 物理像素,但因爲 devicePixelRatio 的做用,設備要求顯示 200px 的物理像素,瀏覽器就智能的填充了像素之間的空格,以便以適當的大小顯示元素。java
在 Safari6 中支持一個屬性 backingStorePixelRatio,該屬性決定了瀏覽器在渲染 canvas 會用幾個像素來繪製畫布的信息。有些相似於 devicePixelRatio。Safari6 的值爲 2,因此在 Safari6 中 canvas 不會模糊,但後來去掉了,如今瀏覽器不支持這個屬性,具體見 Issue 277205。git
解決的思路就是經過檢測設備像素比,繪製對應倍數比例的 canvas 元素。方法以下:github
function createHDCanvas (w=300,h=150) {
var ratio = window.devicePixelRatio || 1;
var canvas = document.createElement('canvas');
canvas.width = w * ratio; // 實際渲染像素
canvas.height = h * ratio; // 實際渲染像素
canvas.style.width = `${w}px`; // 控制顯示大小
canvas.style.height = `${h}px`; // 控制顯示大小
canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
return canvas;
}
複製代碼
這是對比示例,掃描訪問二維碼以下。canvas