如何用CSS/JS调整Canvas位置并解决扩展后动画不生效问题?
问题解决:Canvas扩展后圆形动画不跟随的问题
问题描述
我是第一次在这里提问,刚接触HTML、CSS和JavaScript。我想实现的效果和我制作的网站模型图一致,现在用一段JavaScript代码替换模型里的左侧矩形,代码来自一个Codepen示例。我已经把Canvas往右移动了一点,但扩展Canvas的宽高后,Canvas本身变大了,可里面的圆形动画却没有跟着扩展,请问该如何解决?
问题根源
你的代码里多处使用了浏览器窗口的宽高(innerWidth/innerHeight),而不是Canvas自身的宽高,导致动画始终被限制在浏览器窗口范围内,和你设置的Canvas实际尺寸(800x1600)脱节。另外,鼠标坐标是相对于窗口的,没有转换成Canvas内部的坐标,也会导致交互区域错位。
解决方案
1. 统一绑定Canvas自身的宽高
把所有涉及尺寸判断、位置计算的innerWidth替换为canvas.width,innerHeight替换为canvas.height,包括:
- 圆形的边界碰撞检测
- 圆形初始化的随机位置
- 清屏操作的范围
2. 修正鼠标坐标计算
通过Canvas的getBoundingClientRect()获取其在页面中的位置,将窗口鼠标坐标转换为Canvas内部的相对坐标,确保交互区域正确。
3. 调整Resize逻辑
如果不需要Canvas跟随窗口 resize,就移除resize事件里修改Canvas宽高的代码;如果需要,也要保证所有动画相关的尺寸都同步使用Canvas的新尺寸。
修改后的完整代码
JavaScript部分
var canvas = document.querySelector("canvas") // 设置Canvas的固定尺寸 canvas.width = 800; canvas.height = 1600; var c = canvas.getContext("2d"); var mouse = {x: canvas.width/2, y: canvas.height/2} // 修正鼠标坐标:转换为Canvas内部相对坐标 window.addEventListener("mousemove",(event)=>{ const rect = canvas.getBoundingClientRect(); mouse.x = event.x - rect.left; mouse.y = event.y - rect.top; }) // 如果不需要Canvas随窗口resize,可移除这个事件监听 window.addEventListener("resize",()=>{ // 这里可以根据需求调整Canvas尺寸,比如保持固定或按比例缩放 // canvas.width = 800; // canvas.height = 1600; init(); }) function Circle(x, y, dx, dy, radius, color) { this.x = x; this.y = y; this.dx = dx; this.dy = dy; this.radius = radius; this.originalRadius = radius; // 保存初始半径,用于恢复 this.color = color var maxRadius = 30; this.draw = function() { c.beginPath(); c.arc(this.x,this.y,this.radius,0,Math.PI * 2,false); c.fillStyle = color c.fill(); } this.update = function(){ // 使用Canvas宽高做边界检测 if(this.x + this.radius > canvas.width || this.x - this.radius < 0) { this.dx = -this.dx; } if(this.y + this.radius > canvas.height || this.y - this.radius < 0 ) { this.dy = -this.dy; } // 鼠标交互逻辑 if( mouse.x - this.x > -50 && mouse.x - this.x < 50 && mouse.y - this.y > -50 && mouse.y - this.y < 50) { if (this.radius < maxRadius) { this.radius += 1 } } else { if (this.radius > this.originalRadius) { this.radius -= 1 } } this.x += this.dx; this.y += this.dy; this.draw(); } } var colorArray = ["#F5871A","#81968F","#DFAA2F","#D76034","#F5411D"]; var circleArray = [] function init() { circleArray = [] for (let i = 0; i < 700; i++) { // 基于Canvas宽高生成随机位置 var x = Math.random() * canvas.width; var y = Math.random() * canvas.height ; var radius = Math.random() * 5 + 2; var dx = Math.random() - 0.5; var dy = Math.random() - 0.5; var color = colorArray[Math.floor(Math.random() * colorArray.length)] circleArray.push(new Circle(x,y,dx,dy,radius,color)) } } init() function animate() { requestAnimationFrame(animate); // 基于Canvas宽高清屏 c.clearRect(0,0,canvas.width,canvas.height) for (let i = 0; i < circleArray.length; i++) { circleArray[i].update() } } animate();
CSS部分
.mediaViewInfo { --web-view-name: Homepage; --web-view-id: Homepage; --web-scale-on-resize: true; --web-show-navigation-controls: true; --web-enable-deep-linking: true; --web-page-font: arial, Manrope; } :root { --web-view-ids: Homepage; } * { margin: 0; padding: 0; box-sizing: border-box; border: none; } #Homepage { position: absolute; width: 100%; height:450%; font-family: arial, Manrope; background-color: rgba(255,255,255,1); overflow: hidden; --web-view-name: Homepage; --web-view-id: Homepage; --web-scale-on-resize: true; --web-show-navigation-controls: true; --web-enable-deep-linking: true; --web-page-font: arial; } canvas { background: #FFFF05; background-image: linear-gradient(to bottom, #81968F99, #FFE636CC, #FF000066); margin: 50% 0% 0% 8%; padding: 0; z-index:-1; /* 保持Canvas的实际尺寸,不要用auto导致缩放 */ width: 800px; height: 1600px; } #Wave_Vid { position: absolute; left: -19px; top: -1920px; width: 100vh; height: 100vh; overflow: hidden; } .Wave_container { overflow: visible; } #MIDDLEcontainer { position:absolute; top: 24%; left:59%; } #MIDDLE { overflow: visible; } #Good_ideas_can_take_time { line-height: 0.8; width: 100%; text-align: left; padding-right: 10%; font-family: Manrope, arial; font-style: normal; font-weight: bold; font-size: 15vh; color: rgba(129,150,143,1); margin-bottom: 30px; } #And_execution_takes_even_more { width: 100%; line-height: 1em; text-align: left; padding-right: 30vh; font-family: Manrope, arial; font-style: normal; font-weight: normal; font-size: 5vh; color: rgba(129,150,143,1); margin-bottom: 20px; } #Line_ { fill: transparent; stroke: rgba(129,150,143,1); stroke-width: 4px; stroke-linejoin: miter; stroke-linecap: butt; stroke-miterlimit: 4; shape-rendering: auto; } .Line_ { width: 509px; height: 10px; transform: matrix(1,0,0,1,0,0); margin-bottom: 40px; } #Midcontainer { position:absolute; } #Mid { position:absolute; } .MySkills { position: relative; overflow:visible; height: 1em; text-align: left; font-family: Manrope, arial; font-style: normal; font-weight: lighter; font-size: 12vh; color: rgba(129,150,143,1); letter-spacing: -0.85px; }
HTML部分
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>wbdg portfolio</title> <link rel="stylesheet" type="text/css" id="applicationStylesheet" href="../faux styles.css"/> </head> <body> <div> <canvas></canvas> <script id="jssomething" type="text/javascript" src="../faux scripts.js"></script> <script src="https://kit.fontawesome.com/4f3ce16e3e.js" crossorigin="anonymous"></script> <div id="MIDDLEcontainer"> <div id="MIDDLE"> <div id="Good_ideas_can_take_time"> <p>Good ideas can take time.</p> </div> <div id="And_execution_takes_even_more"> <span>And execution takes even more.</span> </div> <svg class="Line_" viewBox="0 0 674 4"> <path id="Line_" d="M 0 0 L 674 0"> </path> </svg> <div id="Midcontainer"> <div id="Mid"> <div class="MySkills"> Photos </div> <div class="MySkills"> Illustrations </div> <div class="MySkills"> Videos </div> <div class="MySkills"> Animations </div> <div class="MySkills"> Branding </div> </div> </div> </div> </div> </div> </body> </html>
内容的提问来源于stack exchange,提问作者webdog
相关产品推荐
相关产品推荐

