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

如何实现鼓机Canvas网格方块点击切换为crimson颜色?

实现Canvas鼓机方块的点击交互功能

核心问题分析

Canvas是位图绘制,绘制的方块只是像素集合,没有独立的DOM元素,无法直接给单个方块绑定事件。需要通过记录方块的位置数据,在Canvas的全局点击事件中计算点击坐标对应的方块,更新状态后重新绘制画布。

完整解决方案代码

<canvas id="canvas" width="1920" height="1080"></canvas>

<script>
const drums = ["Crash", "CHiHat", "OHiHat", "Tom3", "Tom2", "Tom1", "Snare", "Kick"];
const rowCount = 8;
const colCount = 16;
const blockSize = 50;
const blockGap = 5; // 对应你代码里55 = 50(方块大小)+5(间距)
const startX = 100;

// 初始化网格状态:false=默认灰色,true=crimson
const grid = Array(rowCount).fill().map(() => Array(colCount).fill(false));

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// 封装绘制网格的函数,状态变化后调用重绘
function drawGrid() {
    // 先清空画布,避免旧绘制内容残留
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    for (let i = 0; i < rowCount; i++) {
        for (let v = 0; v < colCount; v++) {
            const x = startX + (blockSize + blockGap) * v;
            const y = (blockSize + blockGap) * i;
            
            // 根据状态设置填充色
            ctx.fillStyle = grid[i][v] ? 'crimson' : '#ddd';
            ctx.fillRect(x, y, blockSize, blockSize);
            ctx.strokeRect(x, y, blockSize, blockSize);
        }
    }
}

// 给Canvas绑定点击事件
canvas.addEventListener('click', (e) => {
    // 将鼠标全局坐标转换为Canvas内部相对坐标
    const rect = canvas.getBoundingClientRect();
    const clickX = e.clientX - rect.left;
    const clickY = e.clientY - rect.top;
    
    // 计算点击对应的行列
    const col = Math.floor((clickX - startX) / (blockSize + blockGap));
    const row = Math.floor(clickY / (blockSize + blockGap));
    
    // 校验点击位置是否在有效方块范围内
    if (col >= 0 && col < colCount && row >= 0 && row < rowCount) {
        // 切换方块状态:点击后反转颜色
        grid[row][col] = !grid[row][col];
        // 重绘网格更新视图
        drawGrid();
    }
});

// 页面加载时初始绘制网格
drawGrid();
</script>

关键改进说明

  • 状态存储:用二维数组grid记录每个方块的激活状态,解决Canvas绘制后丢失方块信息的问题。
  • 绘制封装:drawGrid函数统一处理画布清空与方块绘制,状态变化后只需调用该函数即可更新视图。
  • 坐标转换:通过getBoundingClientRect()将鼠标全局坐标转为Canvas内部坐标,确保点击位置计算准确。
  • 边界校验:避免点击Canvas空白区域时触发无效的数组操作。

原代码的问题点

  1. 循环内重复获取canvas和context,冗余且低效。
  2. 未存储方块的位置与状态,无法在点击时定位到具体方块。
  3. 没有重绘逻辑,绘制完成后无法更新方块颜色。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:20:38