一、最終效果
為了不浪費大家時間,先展示最終效果,看看是不是大家需要的解決方案:
標準分辨率:
其他分辨率的適配情況:
二、需求
1.canvas的內容能全部展示在屏幕上
2.盡量能保證圖像不變形
3.繪制的文字也能自適應
三、解決方案
1.我們需要指定一個標準分辨率gameW和gameH
2.我們需要獲取屏幕的實際分辨率:
screenW=document.documentElement.clientWidth
screenH=document.documentElement.clientHeight
3.把canvas的寬高設置為屏幕一樣大
4.計算屏幕寬度與標準寬度的比值:
kW=screenW/gameW
5.適配之后的繪圖區高度可能小于屏幕高度,所以會出現黑邊。那么我們需要計算黑邊的高度:
dY = (screenH - gameH * kW) / 2;??? //黑色區域的高度(紫色區域頂部與屏幕頂部的距離)
注意,當dY小于0時,繪圖區會超出屏幕范圍,這時就需要壓縮繪圖區高度(這時,畫面會有所變形,也是不可避免的事):
//我們先根據寬度比例適配
let dY = (screenH - gameH * kW) / 2; //黑色區域的高度(紫色區域頂部與屏幕頂部的距離)
//當dY小于0時,我們不得不把畫面給縱向壓縮了。不然部分內容就會到屏幕外面去了
if (dY<0){
dY=0;
kH=screenH/gameH;
}
let scaleH = kW; //高度縮放率,默認以寬度比例
if (kH!==1){
scaleH=kH;
}
最后,還有一個重要的問題,字體大小的自適應。我想到的最簡單的方法就是使用雙緩沖機制,我們繪圖、繪制文字都在另一個緩沖canvas上進行,最后根據scaleH進行縮放,把緩沖canvas的內容繪制到屏幕canvas上。
四、完整代碼
核心代碼:
let canvas = document.getElementById("main");
let ctx = canvas.getContext("2d");
let screenW = document.documentElement.clientWidth; //屏幕寬度
let screenH = document.documentElement.clientHeight; //屏幕高度
let gameW = 640, gameH = 1280; //標準分辨率,也就是你開發時的分辨率 TODO:這里可以自行修改
let kW = screenW / gameW; //屏幕寬度與標準寬度的比值
let kH = 1; //屏幕高度與標準高度的比值
//我們先根據寬度比例適配
let dY = (screenH - gameH * kW) / 2; //黑色區域的高度(紫色區域頂部與屏幕頂部的距離)
//當dY小于0時,我們不得不把畫面給縱向壓縮了。不然部分內容就會到屏幕外面去了
if (dY < 0) {
dY = 0;
kH = screenH / gameH;
}
let scaleH = kW; //高度縮放率,默認以寬度比例
if (kH !== 1) {
scaleH = kH;
}
//設置canvas的絕對大小與屏幕一致
canvas.width = screenW;
canvas.height = screenH;
//緩沖區
let canvasBuffer = document.createElement("canvas");
let ctxBuffer = canvasBuffer.getContext("2d");
//緩沖區使用標準分辨率
canvasBuffer.width = gameW;
canvasBuffer.height = gameH;
let timer = setInterval(mainLoop, 32); //60FPS
let testImg = NewImage('./test.png', 200, 250); //測試圖片
//游戲主循環
function mainLoop() {
drawFillRect(ctx, '#000', 0, 0, canvas.width, canvas.height); //給canvas刷上一層黑色背景~
drawFillRect(ctxBuffer, '#FF00FF', 0, 0, gameW, gameH); //給游戲區域刷上一層紫色背景~
drawText(ctxBuffer, '#FFF', 25, '窗口width:' + screenW, 0, 0);
drawText(ctxBuffer, '#FFF', 25, '窗口height:' + screenH, 0, 30);
drawText(ctxBuffer, '#FFF', 25, 'kW:' + kW, 0, 60);
drawText(ctxBuffer, '#FFF', 25, 'kH:' + kH, 0, 90);
drawText(ctxBuffer, '#FFF', 25, 'dY:' + dY, 0, 120);
drawSrcImg(ctxBuffer, testImg, 100, 100);
drawText(ctxBuffer, '#000', 32, '柳逐霓', 150, 350);
drawSrcImg(ctxBuffer, testImg, 270, 100);
drawText(ctxBuffer, '#000', 32, '柳逐霓', 320, 350);
drawSrcImg(ctxBuffer, testImg, 530, 100);
drawText(ctxBuffer, '#000', 32, '柳逐霓', 580, 350);
drawSrcImg(ctxBuffer, testImg, 100, 400);
drawText(ctxBuffer, '#000', 32, '柳逐霓', 150, 650);
drawSrcImg(ctxBuffer, testImg, 100, 700);
drawText(ctxBuffer, '#000', 32, '柳逐霓', 150, 950);
drawSrcImg(ctxBuffer, testImg, 100, 1000);
drawText(ctxBuffer, '#000', 32, '柳逐霓', 150, 1250);
//雙緩沖
ctx.drawImage(canvasBuffer, 0, 0, gameW, gameH, 0, dY, screenW, gameH * scaleH);
}
狡猾的皮球
發布了40 篇原創文章 · 獲贊 99 · 訪問量 12萬+
私信
關注
標簽:canvas,drawText,let,HTML5,dY,ctxBuffer,屏幕
來源: https://blog.csdn.net/qq_39687901/article/details/104071957