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

Odin项目Etch-A-Sketch作业按钮调整div网格大小失效问题

Etch-A-Sketch 网格调整功能修复方案

先直接答你问的两个思路问题:

  • 用计数器变量存当前网格单侧边的方块数量,更新数值后传给makeDivs重绘网格的思路完全正确。
  • 调整尺寸前先清空容器内所有旧方块的思路是对的——直接在现有元素基础上新增会导致CSS Grid布局排布错乱,全量清空重绘是实现成本最低、最不容易出边界bug的方案,完全没必要硬做增量添加。

你代码里的几个核心问题

  • More按钮绑定了多套互相冲突的事件逻辑:最开始批量给按钮加监听的forEach里,已经绑了点击触发moreDivs,后面又单独给它加了click、dblclick监听,还覆盖了onclick、ondblclick属性,点一次按钮触发三四段逻辑,数值直接乱掉。
  • 事件回调的参数取值逻辑错了:DOM事件的回调函数只会自动传入事件对象作为第一个参数,根本不会读你定义的全局num变量,你写的moreDivs(event, num)里的num是undefined,算出来的网格数是NaN,自然生成不了新网格。
  • 存方块元素的squares是页面第一次加载16*16网格时取的静态集合,后面重绘生成的新方块根本不在这个集合里,所以颜色切换、重置、橡皮擦功能都只会对最开始那批旧方块生效,新方块完全不响应,这就是你颜色按钮失效的原因。
  • 颜色切换逻辑有冗余问题:每次点颜色按钮就给所有现存方块加一层hover监听,点的次数多了会堆很多重复监听,不仅卡,逻辑也容易乱。

修正后的JS代码

直接替换你原来的main.js内容就行,Less按钮的逻辑补了基础版本,你要改步长、调整尺寸上下限可以自己改:

// 显式获取网格容器
const container = document.getElementById("container");
const btnContainer = document.createElement("div");
btnContainer.classList.add("btn-container");

const resetBtn = document.createElement("button");
resetBtn.textContent = "Reset";
const eraserBtn = document.createElement("button");
eraserBtn.textContent = "Eraser";
const moreBtn = document.createElement("button");
moreBtn.textContent = "More";
const lessBtn = document.createElement("button");
lessBtn.textContent = "Less";
const whiteBtn = document.createElement("button");
whiteBtn.textContent = "White";
const blackBtn = document.createElement("button");
blackBtn.textContent = "Black";
const colorBtn = document.createElement("button");
colorBtn.textContent = "Color";

btnContainer.append(
  resetBtn,
  eraserBtn,
  moreBtn,
  lessBtn,
  whiteBtn,
  blackBtn,
  colorBtn
);

document.querySelector("h1").insertAdjacentElement("afterend", btnContainer);

// 全局状态
let gridSize = 16;
let currentDrawColor = "black";

// 统一绑定按钮事件,移除重复监听
document.querySelectorAll("button").forEach(btn => {
  btn.className = "btn";
  btn.addEventListener("click", () => {
    switch (btn) {
      case resetBtn:
        gridSize = 16;
        currentDrawColor = "black";
        renderGrid();
        break;
      case eraserBtn:
        currentDrawColor = "beige";
        break;
      case moreBtn:
        // 加尺寸上限,避免方块太小页面卡顿
        if (gridSize < 100) gridSize += 3;
        renderGrid();
        break;
      case lessBtn:
        // 加尺寸下限,避免数值小于1报错
        if (gridSize > 4) gridSize -= 3;
        renderGrid();
        break;
      case whiteBtn:
        currentDrawColor = "white";
        break;
      case blackBtn:
        currentDrawColor = "black";
        break;
      case colorBtn:
        currentDrawColor = "random";
        break;
    }
  });
});

// 统一网格渲染函数
function renderGrid() {
  // 先清空旧方块
  clearGrid();
  container.style.display = "grid";
  container.style.gridTemplateRows = `repeat(${gridSize}, 1fr)`;
  container.style.gridTemplateColumns = `repeat(${gridSize}, 1fr)`;
  
  for (let i = 0; i < gridSize * gridSize; i++) {
    const square = document.createElement("div");
    square.className = "square";
    // 生成方块时只绑一次hover事件,不用每次换颜色重复绑定
    square.addEventListener("pointerover", () => {
      if (currentDrawColor === "random") {
        const r = Math.floor(Math.random() * 255);
        const g = Math.floor(Math.random() * 255);
        const b = Math.floor(Math.random() * 255);
        square.style.background = `rgb(${r}, ${g}, ${b})`;
      } else {
        square.style.background = currentDrawColor;
      }
    });
    container.append(square);
  }
}

function clearGrid() {
  while (container.firstChild) {
    container.removeChild(container.firstChild);
  }
}

// 初始化渲染网格
renderGrid();

//       ***NOTE TO SELF***            see:
//  @chewdev on github for touchevent code example

HTML和CSS部分不用改动,直接用你原来的代码即可,替换JS之后More/Less调整密度、颜色切换、重置、橡皮擦功能都可以正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:39:18