天天看點

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

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

點選上方“前端自習課”關注,學習起來~

一、問題分析

使用

canvas

繪制圖檔或者是文字在 Retina 屏中會非常模糊。如圖:

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

因為

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