原文鏈接:canvas總結:元素大小與繪圖表面大小
前言
我們使用canvas的時候一般在canvas元素中直接設置它的width和height:
1
|
<canvas id=
"myCanvas"
width=
"300"
height=
"150"
>browser don't support canvas</canvas>
|
當然,也可以不在canvas中進行設置,直接在css樣式中設置,因為canvas本身也是一個html節點
1
|
canvas{width:600px;height:300px}
|
設置以后,打開頁面,發現canvas畫布展示大小也ok,這個時候,我們在上面畫一個40*40矩形,看下效果
1
2
3
4
5
|
var
canvas = document.getElementById(
'canvas'
),
context = canvas.getContext(
'2d'
);
context.fillStyle =
'cornflowerblue'
;
context.fillRect(0, 0, 40, 40);
|
運行頁面,展示如下
canvas大小為600px,高為300px,沒有任何問題,符合預期。但是矩形...這顯然不是40*40好吧,這是80*80
為什么會發生這種情況呢?
canvas的元素大小與繪圖表面大小
canvas的大小分為兩種,一個是canvas作為html元素本身的尺寸,另外一個canvas作為繪圖容器的繪圖表面大小。
在canvas元素中設置寬高,同時指定了canvas的元素尺寸以及繪圖表面的尺寸,兩者相等,繪圖不會有任何問題
但如果使用css設置canvas高寬,其實只是指定了canvas的元素尺寸,而不會影響canvas的繪圖表面的尺寸,如果兩者尺寸是一致的,並不會產生什么問題,但如果不一致,就會出現各種奇怪的問題,這個時候瀏覽器會有自動縮放的機制,對繪圖表面進行縮放,使之適應canvas元素的尺寸。
看我們前面的例子,canvas元素以及繪圖表面的尺寸是300*150,但css中設置了canvas元素尺寸是600*300,實際矩形的繪制是在300*150的繪圖表面中進行繪制的,繪制完成以后要顯示在canvas元素中,需要進行縮放,故產生了圖形變化的問題。
在前面的例子我們打印一下日志:
1
2
3
|
var
box = canvas.getBoundingClientRect();
//canvas元素的邊界框
console.log(canvas.width +
"---"
+ canvas.height)
//300-150
console.log(box.width +
"---"
+ box.height);
//600-300
|
其中canvas對象獲取的其實是繪圖表面大小,box獲取的是canvas元素的大小
那縮放的規則是什么?
我們用幾個例子來看一下
1. css中設置canvas元素600*300,繪圖表面300*100,畫矩形40*40
實際矩形80*120
寬度是預期的兩倍,高度是預期3倍
2. Css中設置canvas元素600*300,繪圖表面200*150,畫矩形40*40
實際矩形120*80
寬度是預期的3倍,高度是預期的2倍
3. Css中設置canvas元素600*300,繪圖表面1200*900,畫矩形60*60
實際矩形30*20
寬度是預期的1/2,高度是預期的1/3
4. Css中設置canvas元素600*300,繪圖表面1800*600,畫矩形60*60
實際矩形20*30
寬度是預期的1/3,高度是預期的1/2
我們用element表示canvas元素,用canvas表示繪圖表面,src表示繪制的內容,dest表示展示的內容,縮放規則為:dest.size = src.size * (element.size / canvas.size)
其它
其實不僅僅是大小縮放的問題,坐標也會偏移,在canvas中畫圓,如果canvas元素與繪圖表面的尺寸不一致,會發現實際展示的圓心位置並不是你指定的坐標,實際展示的坐標位置同樣遵循上面所述的規則。
當然,解決這些問題非常簡單,就是不要使用css來指定canvas元素大小,保持canvas元素尺寸與繪圖表面尺寸的一致性
自適應
當我們在說自適應的時候,我們說的是 css layout dimensions 自適應,亦即元素的 display size。
而 canvas 的 width/height 屬性對應的是畫布內的 coordinate space,並不歸 CSS 管。
於是,canvas 的顯示大小可以由 CSS 規則指定,做到顯示自適應,但其內部像素並不對應 CSS 像素或屏幕物理像素,也就是說縮放顯示。
===========================================
如果你需要讓 canvas 的 coordinate space 始終跟隨窗口大小的話,可以用 js 設定 canvas 高寬為窗口高寬 x 設備像素密度,並且監聽 window resize 事件,使 canvas 高寬隨着窗口大小的變化而變化。
另外, canvas 的高寬改變時,畫布內容會被清空,需要重新繪制。