
點選上方“前端自習課”關注,學習起來~
一、問題分析
使用
canvas
繪制圖檔或者是文字在 Retina 屏中會非常模糊。如圖:
因為
canvas
不是矢量圖,而是像圖檔一樣是位圖模式的。高
dpi
顯示裝置意味着每平方英寸有更多的像素。也就是說二倍屏,浏覽器就會以 2 個像素點的寬度來渲染一個像素,該
canvas
在 Retina 螢幕下相當于占據了2倍的空間,相當于圖檔被放大了一倍,是以繪制出來的圖檔文字等會變模糊。
是以,要做 Retina 屏适配,關鍵是知道目前螢幕的裝置像素比,然後将
canvas
放大到該裝置像素比來繪制,然後将
canvas
壓縮到一倍來展示。
二、解決思路
在浏覽器的
window
對象中有一個
devicePixelRatio
的屬性,該屬性表示了螢幕的裝置像素比,即用幾個(通常是 2 個)像素點寬度來渲染 1 個像素。
舉例來說,假設
devicePixelRatio
的值為 2 ,一張
100×100
像素大小的圖檔,在 Retina 螢幕下,會用 2 個像素點的寬度去渲染圖檔的 1 個像素點,是以該圖檔在 Retina 螢幕上實際會占據
200×200
像素的空間,相當于圖檔被放大了一倍,是以圖檔會變得模糊。
類似的,在 canvas
context
中也存在一個
backingStorePixelRatio
的屬性,該屬性的值決定了浏覽器在渲染
canvas
之前會用幾個像素來來存儲畫布資訊。
backingStorePixelRatio
屬性在各浏覽器廠商的擷取方式不一樣,是以需要加上浏覽器字首來實作相容。
三、解決問題
1. 首先一樣,擷取
Canvas
對象:
var myCanvas = document.getElementById("my_canvas");var context = myCanvas.getContext("2d");
複制
2. 擷取像素比,将
Canvas
寬高進行放大,放大比例為:
devicePixelRatio/webkitBackingStorePixelRatio
, 我們寫了一個相容的方法。
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(context);
複制
3. 按實際渲染倍率來縮放
canvas
。
注意基礎知識點:
- 要設定
的畫布大小,使用的是canvas
和canvas.width
;canvas.height
- 要設定畫布的實際渲染大小,使用的
屬性或style
設定的CSS
和width
,隻是簡單的對畫布進行縮放。height
2倍螢幕下示例代碼:
<canvas width="640" height="800" style="width:320px; height:400px"></canvas>
複制
canvas
的實際大小的
640px×800px
,但是實際渲染到頁面的大小是
320px×400px
,相當于縮小一倍來顯示。
那麼在3倍螢幕下就是:
<canvas width="960" height="1200" style="width:320px; height:400px"></canvas>
複制
是以,要使
canvas
适配高倍屏,就是要将
canvas
放大到裝置像素比來繪制,最後将
canvas
壓縮成一倍的實體大小來展示。如下:
myCanvas.style.width = myCanvas.width + 'px';myCanvas.style.height = myCanvas.height + 'px';myCanvas.width = myCanvas.width * ratio;myCanvas.height = myCanvas.height * ratio;
複制
4. 繪制
由于
Canvas
放大後,相應的繪制圖檔時也要放大,有兩種方式:
第一種方法:每一個繪制相應的放大,比如我們繪制文字:
context.font = "36px Georgia"; //一倍屏下18px字型
context.fillStyle = "#999";
context.fillText("我是清晰的文字", 50*ratio, 50*ratio);// 坐标位置乘以像素比
複制
相對來說這個方法非常繁瑣麻煩。
第二種方法:直接使用
scale
方法:
// 放大倍數context.scale(ratio, ratio);context.font = "18px Georgia";context.fillStyle = "#999";context.fillText("我是清晰的文字", 50, 50);
複制
這樣就可以解決
canvas
在高清屏中繪制模糊的問題。
完整的demo:https://www.html.cn/demo/canvas_retina/index.html