圖形編輯器:適配高分辨率屏幕
大家好,我是前端西瓜哥。我的圖形編輯器項目一直都是用一個 1080P 的老顯示器開發的。
但最近我改用 Macbook Pro 的視網膜 (Retina) 屏幕開發時,發現高分屏(高分辨率屏幕)反而讓圖形編輯器中的線變得模糊了。
這次我們來看看該如何解決這個問題。
項目地址,歡迎 star:
https://github.com/F-star/suika
線上體驗:
https://blog.fstars.wang/app/suika/
高分屏
表達代碼中的一個像素(獨立像素),原本是只需要一個屏幕的一個發光單元(物理像素),一對一關系,很好理解。
但隨著顯示器的發展,我們有了更小尺寸的發光單位,可以在原本一個發光單元的空間上放上更多的小發光單元。
這種情況下,如果還是一個發光單元對應一個代碼中的像素,會導致繪制的圖形變小,遠看看不清楚。
怎么辦,我們的方案是 用多個發光單元表示一個代碼中的像素。比如 Mac 的視網膜 (Retina) 屏幕,會將獨立像素寬高乘以 2,映射到 4 個發光單元上。
但不一定會將多個點設置相同的顏色,而是會在一些情況下做抗鋸齒處理,所以在高分屏中會發現鋸齒少了,看起來高清多了,但也會讓原本就是想要鋸齒狀的邊緣變得光滑。
devicePixelRatio
devicePixelRatio (通常我們用 dpr 變量名)是設備像素比,指的是當前顯示設備的物理像素分辨率與CSS 像素分辨率之比。
這個定義有點抽象,其實就是前文我說的那些。對于 Mac 的視網膜 (Retina) 屏幕,它的 devicePixelRatio 是 2,也就是將一個 CSS 像素寬高各乘以 2,繪制到屏幕的 4 個發光單元上。
我們可以通過 window.devicePixelRatio 拿到瀏覽器所在屏幕的設備像素比。
Canvas 的處理
Canvas 繪制的像素(比如線條),在高分屏中,會因為繪制成 4 個點(即發光單元),變得更粗,此外也會因為抗鋸齒處理造成模糊。
在 IOS App 的 UI 設計中,有一種 ??@2x?
??,??@3x?
? 圖的概念。就是將圖片放大 2 倍和 3 倍進行設計,然后渲染時尺寸指定回原來的尺寸進行繪制。
這樣屏幕渲染時能拿到更多的像素細節,做到一個像素對應一個發光單元,不是基于一個 1x1 的像素,去放大為 2x2 或 3x3,而丟失細節。
Canvas 本質也是一張圖片,它的 ??width?
?? 和 ??height?
?? 屬性代表該圖片的原始寬高, ??style.width?
?? 和 ??style.height?
? 則是實際渲染寬高。
所以解決方法是,將 Canvas 原始寬高設置為容器寬度的 devicePixelRatio 倍,然后再用 style.width 和 style.height 設置為容器寬高。
然后 Canvas 在繪制圖形前,將縮水的 Canvas 通過縮放變形恢復原來的尺寸。
結尾
總結一下,就是高分屏有更小的發光單元,一般情況下會用 2x2、3x3 個點去表示一個像素,一些情況下會讓鋸齒邊緣變得光滑,但也可能會讓清晰的線條的邊緣變得模糊。
對于圖片和 Canvas,可以擴大對應的 devicePixelRatio 倍數,然后再縮放為頁面中容器的大小,這樣顯示器就能拿到完整的像素信息了,就不會應為放大而失真。