
本文详解如何通过 javascript 实现 canvas 中矩形的双色(红/绿)点击切换,并支持无限循环,避免阻塞主线程,同时提供可复用、高性能的解决方案。
本文详解如何通过 javascript 实现 canvas 中矩形的双色(红/绿)点击切换,并支持无限循环,避免阻塞主线程,同时提供可复用、高性能的解决方案。
在 HTML5 Canvas 中,直接修改 fillStyle 并重绘矩形即可改变颜色,但要实现「点击一次切到绿色,再点切回红色,无限循环」,关键在于状态管理——需记录当前颜色,而非硬编码切换逻辑。原始代码中每次点击都强制设为绿色,缺乏状态判断,因此无法回切。
下面是一个简洁、健壮且符合现代 Web 实践的实现方案:
✅ 推荐方案:使用布尔状态 + 重绘逻辑
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #ccc; cursor: pointer;"></canvas>
<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
// 初始绘制红色矩形
let isGreen = false;
function drawRect(color) {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布(避免重叠)
ctx.fillStyle = color;
ctx.fillRect(50, 50, 150, 100);
}
drawRect("red"); // 首次渲染红色
// 点击切换逻辑
canvas.addEventListener("click", () => {
isGreen = !isGreen;
drawRect(isGreen ? "green" : "red");
});
</script>? 说明:
Wechat Article Html下载将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 使用
clearRect()清除整个画布,确保每次重绘干净无残留;isGreen作为状态变量,精准控制颜色切换方向;- 事件监听器替代内联
onclick,更易维护、符合最佳实践。
⚠️ 注意事项与常见误区
- ❌ 不要用
while或密集for循环模拟“闪烁”或“自动切换”:这会阻塞浏览器主线程,导致页面卡死、无法响应用户操作; - ❌ 避免在
fillRect()后不清理画布:多次调用会叠加绘制(尤其当尺寸/位置微调时),造成视觉异常; - ✅ 如需动画效果(如淡入淡出、过渡色):Canvas 本身不支持 CSS 过渡,需借助
requestAnimationFrame手动插值,或改用 DOM 元素(如<div> + <code>@keyframes)——正如答案中提到的 CSS 方案,适合纯视觉反馈场景; - ✅ 扩展性建议:若需支持多个 Canvas 独立切换,可封装为函数,传入 canvas 元素和初始颜色,例如:
function setupToggle(canvas, colorA = "red", colorB = "green") { let current = colorA; const ctx = canvas.getContext("2d"); const draw = () => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = current; ctx.fillRect(50, 50, 150, 100); }; draw(); canvas.addEventListener("click", () => { current = current === colorA ? colorB : colorA; draw(); }); } setupToggle(document.getElementById("myCanvas"));
✅ 总结
实现 Canvas 对象的双色循环切换,核心是状态驱动重绘:用一个布尔值或字符串变量记录当前色,点击时取反/轮换,再调用统一绘制函数。该方法轻量、可预测、易调试,且完全兼容标准 Canvas API。避免使用 setTimeout 链式回调或 Promise 延迟切换(除非需要精确节拍动画),因为本需求本质是「用户触发的离散状态切换」,而非时间驱动的连续动画。
立即学习“前端免费学习笔记(深入)”;



















