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

循环中调用HTML Canvas绘制圆角矩形失效问题

问题分析与修复

你的代码存在两个核心问题,导致渲染循环中画布完全空白:

1. 重复循环与实例属性篡改

Letter类的render方法内部嵌套了rows和cols的双重循环,而外部全局render函数已经在遍历整个grid数组调用每个Letter实例的render方法。这意味着每个Letter实例会重复绘制25个圆角矩形,更严重的是,每次调用render时都会把实例的r属性从初始数字(16)改成对象,第二次渲染时this.r已经是对象,再执行this.r = { tl: this.r, tr: this.r, br: this.r, bl: this.r }会生成嵌套对象,导致坐标计算完全错误,最终无法绘制任何图形。

2. 笔误导致坐标失效

绘制右下角圆角的二次贝塞尔曲线时,错误使用了this.t.br——t是你传入的字母(如'B'),没有br属性,这会让undefined参与坐标计算,直接导致路径失效。


修正后的完整代码

const c = document.createElement('canvas');
c.width = innerHeight / 2; 
c.height = innerHeight / 2;
document.getElementById('app').appendChild(c);
const ctx = c.getContext('2d');

class Letter {
    i; x; y; w; h; r; t;
    constructor(i, x, y, w, h, r, t) {
        this.i = i; 
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        // 初始化圆角配置对象,避免后续类型篡改
        this.r = { tl: r, tr: r, br: r, bl: r };
        this.t = t;
    }

    render() {
        ctx.beginPath();
        // 左上角到右上角
        ctx.moveTo(this.x + this.r.tl, this.y);
        ctx.lineTo(this.x + this.w - this.r.tr, this.y);
        ctx.quadraticCurveTo(this.x + this.w, this.y, this.x + this.w, this.y + this.r.tr);
        // 右上角到右下角
        ctx.lineTo(this.x + this.w, this.y + this.h - this.r.br);
        ctx.quadraticCurveTo(this.x + this.w, this.y + this.h, this.x + this.w - this.r.br, this.y + this.h);
        // 右下角到左下角
        ctx.lineTo(this.x + this.r.bl, this.y + this.h);
        ctx.quadraticCurveTo(this.x, this.y + this.h, this.x, this.y + this.h - this.r.bl);
        // 左下角到左上角
        ctx.lineTo(this.x, this.y + this.r.tl);
        ctx.quadraticCurveTo(this.x, this.y, this.x + this.r.tl, this.y);
        ctx.closePath();
        ctx.fillStyle = 'red';
        ctx.fill();
    }
}

const rows = 5, cols = 5;
var grid = [];
var counter = 0;
for (let row = 0; row < rows; row++) {
    grid[row] = [];
    for (let col = 0; col < cols; col++) {
        grid[row][col] = new Letter(
            counter++, 
            ((c.width / rows) * col), 
            ((c.height / cols) * row), 
            Math.round((c.width / rows) - 8),
            Math.round((c.height / cols) - 8),
            16,            
            'B',
        );
    }
}

function render() {
    ctx.clearRect(0, 0, c.width, c.height);
    for (let row = 0; row < rows; row++) {
        for (let col = 0; col < cols; col++) {
            const l = grid[row][col];
            l.render();
        }
    }
    requestAnimationFrame(render);
}

requestAnimationFrame(render);

关键修改说明

  • 移除Letter.render方法内部的双重循环,每个实例仅负责绘制自身对应的圆角矩形
  • 在constructor中直接将r初始化为包含四个角的配置对象,避免后续类型篡改
  • 修正笔误:将this.t.br改为this.r.br,确保坐标计算正确
  • 保留原有网格布局逻辑,保证每个圆角矩形的位置和尺寸准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:20:35