You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 05:24:08