【轉】解決 canvas 在高清屏中繪制模糊的問題


來源: http://www.css88.com/archives/9297

使用 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 對象:

JavaScript 代碼:
var myCanvas = document.getElementById("my_canvas");
var context = myCanvas.getContext("2d");
2.獲取像素比,將 Canvas 寬高進行放大,放大比例為:devicePixelRatio / webkitBackingStorePixelRatio , 我們寫了一個兼容的方法。

JavaScript 代碼:
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倍屏幕下示例代碼:

HTML 代碼:
<canvas width="640" height="800" style="width:320px; height:400px"></canvas>
canvas的實際大小的640px × 800px,但是實際渲染到頁面的大小是320px × 400px,相當於縮小一倍來顯示。

那么在3倍屏幕下就是:

HTML 代碼:
<canvas width="960" height="1200" style="width:320px; height:400px"></canvas>
因此,要使canvas適配高倍屏,就是要將canvas放大到設備像素比來繪制,最后將canvas壓縮成一倍的物理大小來展示。如下:

JavaScript 代碼:
myCanvas.style.width = myCanvas.width + 'px';
myCanvas.style.height = myCanvas.height + 'px';
 
myCanvas.width = myCanvas.width * ratio;
myCanvas.height = myCanvas.height * ratio;
4.繪制

由於 Canvas 放大后,相應的繪制圖片時也要放大,有兩種方式:

第一種方法:每一個繪制相應的放大,比如我們繪制文字

JavaScript 代碼:
context.font = "36px Georgia"; //一倍屏下18px字體
context.fillStyle = "#999";
context.fillText("我是清晰的文字", 50*ratio, 50*ratio);// 坐標位置乘以像素比
相對來說這個方法非常繁瑣麻煩。

第二種方法:直接使用 scale 方法:

JavaScript 代碼:
// 放大倍數
context.scale(ratio, ratio);
 
context.font = "18px Georgia";
context.fillStyle = "#999";
context.fillText("我是清晰的文字", 50, 50);
這樣就可以解決 canvas 在高清屏中繪制模糊的問題

完整的demo:http://www.css88.com/demo/canvas_retina/index.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM