一、最终效果
为了不浪费大家时间,先展示最终效果,看看是不是大家需要的解决方案:
完整项目地址:https://github.com/zxf20180725/canvas_auto-adapted
标准分辨率:
其他分辨率的适配情况:
二、需求
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上。
四、完整代码
完整项目地址:https://github.com/zxf20180725/canvas_auto-adapted
核心代码:
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万+ 私信 关注