如何实现Canvas随浏览器窗口大小自适应调整
解决Canvas随窗口尺寸自适应问题
问题说明
需要让Canvas背景随浏览器窗口任意尺寸变化自动适配,但之前尝试调整后Canvas尺寸始终未改变,相关代码如下:
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>About RatherChaotic</title> <link rel="stylesheet" href="./assets/css/style.css"> <link rel="icon" type="image/x-icon" href="assets/images/pfp.png"> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery.terminal/js/jquery.terminal.min.js"></script> <link rel="stylesheet" href="https://unpkg.com/jquery.terminal@2.x.x/css/jquery.terminal.min.css"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body class="home"> <div class="background"> <script src="assets/js/background.js" type="module"></script> <canvas id="background_canvas">Cannot Render Canvas</canvas> </div> <div class="foreground"> <script src="assets/js/app.js" type="module"></script> <a href="https://github.com/RatherChaotic"><img id="pfp" src="assets/images/pfp.png" alt="My Profile Picture" width="256" height="256"></a> <h1 id="username">RatherChaotic</h1> <p id="wia"></p> </div> <div id="terminal"></div> </body> </html>
style.css
@font-face { font-family: Monocraft; src: url("../Monocraft.ttf"); } body { height: auto; } .background canvas{ position: fixed; left: 0; top: 0; margin: 0; padding: 0; border: 0; overflow-y:scroll; overflow-x: hidden; -webkit-overflow-scrolling: touch; height: auto; width: auto; z-index: -1; } .foreground { background-color: transparent; height: 100%; fill-opacity: 100%; z-index: 100; color: #FFF; } .foreground #pfp { border-radius: 50%; display: block; margin-left: auto; margin-right: auto; position: relative; } .foreground #username { font-family: Monocraft, monospace; font-size: xx-large; margin:auto; text-align:center; top:30px; width:100%; position: relative; } .foreground #wia { position: relative; font-family: Monocraft, monospace; font-size: large; margin:auto; text-align:center; top:40px; width:100%; } #terminal { position: relative; top: 50px; width: 50%; left: 50%; transform: translate(-50%); }
background.js(原始代码)
const canvas = document.getElementById('background_canvas'); const context = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン'; const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const nums = '0123456789'; const alphabet = katakana + latin + nums; const fontSize = 16; const columns = canvas.width/fontSize; const rainDrops = []; for( let x = 0; x < columns; x++ ) { rainDrops[x] = 1; } const draw = () => { context.fillStyle = 'rgba(0, 0, 0, 0.05)'; context.fillRect(0, 0, canvas.width, canvas.height); context.fillStyle = '#0F0'; context.font = fontSize + 'px monocraft'; for(let i = 0; i < rainDrops.length; i++) { const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length)); context.fillText(text, i*fontSize, rainDrops[i]*fontSize); if(rainDrops[i]*fontSize > canvas.height && Math.random() > 0.975){ rainDrops[i] = 0; } rainDrops[i]++; } }; setInterval(draw, 30);
解决方案
要实现Canvas自适应窗口尺寸,需要做以下三处修改:
- 修正CSS中Canvas的样式
移除background canvas中的overflow-y:scroll、width:auto、height:auto,改用width:100vw和height:100vh确保初始占满视口;同时给body添加margin:0和overflow-x:hidden,避免默认边距导致的滚动条。修改后的background canvas和body样式如下:
body { height: auto; margin: 0; overflow-x: hidden; } .background canvas{ position: fixed; left: 0; top: 0; margin: 0; padding: 0; border: 0; z-index: -1; width: 100vw; height: 100vh; }
封装初始化逻辑为可复用函数
将Canvas尺寸设置、列数计算、雨滴数组初始化的代码封装成函数,方便初始化和窗口resize时调用。监听窗口resize事件并防抖
在窗口尺寸变化时,重新调用初始化函数,同时添加防抖逻辑避免频繁触发导致性能问题。
修改后的background.js代码如下:
const canvas = document.getElementById('background_canvas'); const context = canvas.getContext('2d'); const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン'; const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const nums = '0123456789'; const alphabet = katakana + latin + nums; const fontSize = 16; let columns; let rainDrops = []; // 初始化Canvas和雨滴数组 function initCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; columns = canvas.width / fontSize; rainDrops = []; for (let x = 0; x < columns; x++) { rainDrops[x] = 1; } } const draw = () => { context.fillStyle = 'rgba(0, 0, 0, 0.05)'; context.fillRect(0, 0, canvas.width, canvas.height); context.fillStyle = '#0F0'; context.font = fontSize + 'px monocraft'; for(let i = 0; i < rainDrops.length; i++) { const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length)); context.fillText(text, i*fontSize, rainDrops[i]*fontSize); if(rainDrops[i]*fontSize > canvas.height && Math.random() > 0.975){ rainDrops[i] = 0; } rainDrops[i]++; } }; // 初始调用一次 initCanvas(); // 监听窗口resize事件,防抖避免频繁触发 let resizeTimer; window.addEventListener('resize', () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(initCanvas, 200); }); setInterval(draw, 30);
内容的提问来源于stack exchange,提问作者RatherChaotic
相关产品推荐
相关产品推荐

