我們要在頁面上繪畫出遊戲場景,必然要有一個畫布(canvas)。
那麼,我們就來講講如何進行畫布設置吧~
蝦米?你早就會了?canvas.getContext("2d")?
那你就錯了,這裏學問可大着呢。繼續往下看看吧。
首先第一點,我們要了解canvas的分辨率設置。
一般來說,遊戲標準的4:3分辨率是800X600、1024X768。16:9的是960X540、1366X768。
假設,我們想要將一個800X600的畫布拉伸至1024X768應該怎麼做?
難道直接把畫布的width和height設置成1024X768嗎?這很顯然不是拉伸。
其實這裏涉及到了一個關鍵點:硬件縮放。
我們在做一般前端的時候都會使用到css,這裏也不例外。
假設我們有這樣一個元素:
<canvas id="gameCanvas" width="800" height="600"></canvas>
然後我們再加上這段css:
#gameCanvas{
width: 1024px;
height: 768px;
}
如果你在這個畫布中繪製了東西的話就會發現,哇塞~真的縮放了耶!
而且這裏的縮放是硬件縮放,因此,性能將會十分的高(前提是設備支持硬件加速)。
通過以上方式我們知道了如何進行硬件縮放,若你在此之前已經綁定了鼠標事件會發現,怎麼鼠標獲取到X和Y和現在的圖形所顯示的X和Y對不上呢?這該怎麼辦?
這是因爲我們繪製的時候設置的大小是800X600而真實顯示的是1024X768。在這期間畫布中的圖形已經按照比例進行了縮放。因此,我們需要手動計算以彌補差值。
僞公式 :鼠標X * (畫布寬度 / css設置寬度) = 鼠標映射到繪製時使用的分辨率的X位置
套入公式,計算(假設當前鼠標在550X300的位置):550 * (800 / 1024) ≈ 430
因此,計算得出 ,鼠標當前的X位置指向的應該是畫布中繪製的430的位置。
鼠標的Y位置同理。
好的~上面我們已經介紹瞭如何進行硬件縮放且如何獲得鼠標指向的位置。
接下來我們就來通過以上兩個方法做出同比縮放效果吧!
何爲同比縮放?請看圖:
通過上圖我們可以看出,無論我們如何對瀏覽器進行縮放,畫布寬高比永恆不變。
這就是我們所需要的效果了。下面我們就來實現吧!
第一步:計算原始寬高比,假設我們的畫布是800X600的分辨率。那麼寬高比就是:800 / 600 ≈ 1.33
第二步:定義一個函數,根據寬高、上層元素寬高計算縮放值。將縮放值與原始寬高進行計算。將元素顯示到上層元素中心。
function resize(){
// 獲取畫布元素
var canvas = document.getElementById("gameCanvas");
// 畫布元素的上層元素
var pe = canvas.parentElement || canvas.parentNode || document.body;
// 畫布元素的上層元素寬度和高度
var pw = pe.clientWidth;
var ph = pe.clientHeight;
// 畫布元素的寬度和高度
var width = canvas.width;
var height = canvas.height;
// 縮放值
var scaling = Math.min(pw / width, ph / height);
// 設置新寬度和高度
canvas.style.width = (width * scaling) + "px";
canvas.style.height = (height * scaling) + "px";
// 如果當前畫布在body中則顯示在最中央
if (pe == document.body){
canvas.style.marginTop = ((ph - height * scaling) / 2) + "px";
canvas.style.marginLeft = ((pw - width * scaling) / 2) + "px";
}
}
// 綁定事件
window.addEventListener("resize", resize, false);
// 強制使用單屏應用方式
if (pe == document.body){
var ss = document.createElement("style");
ss.innerHTML = "html,body{margin:0;padding:0;width:100%;height:100%;overflow:hidden;}";
document.getElementByTagName("head").item(0).appendChild(ss);
}
這樣就可以了!~
最後的同比縮放加上前面的鼠標位置計算就是完美的應用分辨率自適應了!~
這是一個很簡單但是卻會經常忽略掉的一些處理 。
另外,這個方法在配合使用Fullscreen API的時候會出現一些計算錯誤,只需要修改上面代碼的一小部分就可以搞定,就留作作業吧~!如果真心搞不定,請在評論中留鹽~~~~
最後放一個演示結束~請期待下一篇~