Sketchpad项目修改画布尺寸时出现收缩及点击失效问题求助
解决Etch-a-Sketch画布收缩与点击失效问题
问题根源
- 画布收缩:调用
getBoard时未清除原有方块,新旧方块叠加导致网格布局计算错误,视觉上表现为画布收缩 - 点击功能失效:每次调用
getBoard都会给.board添加新的点击事件监听器,多次触发后事件逻辑叠加,click状态切换混乱
修复方案
修改后的JavaScript代码
let buttons = document.querySelectorAll('[data-color]'); let buttonSize = document.querySelector('.get-size'); let buttonClear = document.querySelector('.clear'); let color = 'black'; let click = true; let clickMessage = document.querySelector('.click-message-on'); let clickMessageOff = document.querySelector('.click-message-off'); let errorMessage = document.querySelector('.error-message'); let board = document.querySelector('.board'); buttons.forEach((button) => { button.addEventListener('click', function changeColor(){ let colorSelection = button.dataset.color; color = colorSelection; }) }) buttonSize.addEventListener('click', function() { let size = getSize(); if (size) getBoard(size, size); }); buttonClear.addEventListener('click', function() { let squares = document.querySelectorAll('.sq'); squares.forEach((square) => { square.style.backgroundColor = 'rgb(235, 135, 99)'; }) }) function getBoard(cols, rows) { // 清空旧画布内容 board.innerHTML = ''; board.style.gridTemplateColumns = `repeat(${cols}, 1fr)` board.style.gridTemplateRows = `repeat(${rows}, 1fr)` let size = cols * rows; for (let i = 0; i < size; i++) { let fill = document.createElement('div'); fill.className = 'sq'; fill.addEventListener('mouseover', getColor); board.insertAdjacentElement('beforeend', fill); } // 替换节点清除旧事件,避免叠加 board.replaceWith(board.cloneNode(true)); board = document.querySelector('.board'); // 重新绑定点击事件 board.addEventListener('click', function() { click = !click; if (click) { clickMessage.textContent = 'Click enabled, you can paint! ✔️'; clickMessageOff.textContent = ''; } else { clickMessageOff.textContent = 'Click disabled, you can\'t paint! ❌'; clickMessage.textContent = ''; } }) } function getColor() { if (click) { this.style.backgroundColor = color; if (color === 'random') { this.style.backgroundColor = `hsl(${Math.random() * 360}, 100%, 50%)`; } } } function getSize() { errorMessage.textContent = ''; let input = prompt('Select a size'); input = parseFloat(input); if (input <= 0) { errorMessage.textContent = 'Negative numbers are not valid!'; } else if (input > 64) { errorMessage.textContent = 'Enter a number between 1 and 64'; } else if (isNaN(input)) { errorMessage.textContent = 'Only numbers allowed'; } else { return input; } } getBoard(32, 32);
关键修改说明
- 清空旧画布:在
getBoard开头添加board.innerHTML = '',彻底移除原有方块,避免新旧元素叠加 - 解决事件叠加:通过
board.replaceWith(board.cloneNode(true))替换节点,清除所有旧事件监听器,再重新绑定一次点击事件,确保逻辑唯一 - 优化输入处理:
getSize中先清空错误信息,用isNaN更准确判断非数字输入,避免无效输入触发画布重建 - 减少DOM查询:提前获取
.board元素,避免重复查询提升性能
效果验证
修改后点击「Select a size」按钮,输入1-64之间的有效尺寸,旧画布会被完全替换,新画布保持500x500固定尺寸,点击开关功能稳定生效,不会出现状态混乱。
内容的提问来源于stack exchange,提问作者Quickpois0n
相关产品推荐
相关产品推荐

