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

为何修改Canvas 2D的fillStyle会改变已绘制矩形的颜色?

Canvas矩形颜色被意外覆盖的问题解决

你遇到的问题核心是Canvas 2D上下文的路径是累积式的:

  • 每次调用ctx.rect()都会把新的矩形路径添加到当前上下文的路径集合里,而非替换原有路径
  • 调用ctx.fill()时,会填充当前路径集合里的所有图形,不是只填充最后添加的那个

所以你的代码里:

  1. 第一次循环中,3个黄色矩形的路径被依次加入路径集合,每次fill()都填充了当时的所有路径(第一次填第一个矩形,第二次填前两个,第三次填三个)
  2. 修改fillStyle为蓝色后调用ctx.fill(),会把路径集合里的全部4个矩形(3个小矩形+1个大矩形)用蓝色填充,导致所有矩形变蓝
  3. 注释第二个fill()后,只有第一次循环的三次fill()生效,大矩形的路径没被填充,所以只显示3个黄色矩形

两种解决方法

方法1:每次绘制前重置路径(用beginPath())

每次绘制新图形前,调用ctx.beginPath()清空当前路径集合,后续的rect()只会添加到新路径,fill()也只填充当前新路径的图形:

const get = id => document.getElementById(id);

const canv = get('canv');
const [w, h] = [canv.width, canv.height];
const ctx = canv.getContext("2d");

// 绘制黄色小矩形
ctx.fillStyle = 'yellow';
for (let x = 0; x < 3; x++) {
  ctx.beginPath(); // 每次绘制前重置路径
  ctx.rect(10*x, 100, 3, 3);
  ctx.fill();
}

// 绘制蓝色大矩形
ctx.fillStyle = 'blue';
ctx.beginPath(); // 重置路径,避免包含之前的矩形
ctx.rect(100, 100, 5, 5);
ctx.fill();

方法2:直接使用fillRect()(更简洁)

fillRect()是直接填充指定矩形的API,会自动创建独立路径并完成填充,不会累积到上下文的路径集合里,代码更简洁:

const get = id => document.getElementById(id);

const canv = get('canv');
const [w, h] = [canv.width, canv.height];
const ctx = canv.getContext("2d");

// 绘制黄色小矩形
ctx.fillStyle = 'yellow';
for (let x = 0; x < 3; x++) {
  ctx.fillRect(10*x, 100, 3, 3); // 直接填充,无需手动路径操作
}

// 绘制蓝色大矩形
ctx.fillStyle = 'blue';
ctx.fillRect(100, 100, 5, 5);

补充说明

  • rect()属于路径构建API,需要配合fill()/stroke()完成绘制,且会累积路径
  • fillRect()/strokeRect()属于直接绘制API,一步完成路径构建和填充/描边,不会累积路径,适合绘制独立的基础图形

内容的提问来源于stack exchange,提问作者user9163823

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 23:02:34