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
相关产品推荐
相关产品推荐

