HTML5 canvas自适应手机屏幕大小的一种解决方案
一、最终效果
为了不浪费大家时间,先展示最终效果,看看是不是大家需要的解决方案:
完整项目地址: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); //60FPSlet 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);}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
