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

Etch-A-Sketch项目两大功能异常问题求助

Etch-A-Sketch 问题修复方案

问题1:Opacity按钮切换后无法递增透明度

原因

  1. 每次点击工具按钮时,都会给单元格添加新的mouseenter监听器,多个监听器叠加导致Opacity逻辑被其他工具覆盖。
  2. Clear按钮将单元格backgroundColor设为#ffffff,Opacity逻辑仅识别rgba格式的背景色,白色不会触发递增分支,只会重置为0.1透明度的黑色。
  3. 直接从样式字符串解析透明度易受浏览器格式差异影响,可靠性低。

修复方案

  • 用全局变量记录当前激活工具,统一在单元格的mouseenter事件中执行对应逻辑,避免重复绑定监听器。
  • 给每个单元格添加自定义属性存储透明度值,替代从样式字符串解析的方式。

问题2:Clear后Grid背景色无法显示

原因

Clear按钮将单元格backgroundColor设为不透明的#ffffff,完全覆盖了Grid的背景色,导致Grid背景无法透出。

修复方案

  • Clear时将单元格backgroundColor设为空字符串,让Grid背景色正常显示。

修改后的完整代码

HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <script src="app.js" defer></script>
    <title>Etch-A-Sketch</title>
</head>

<body>
    <header>
        <h1>Etch-A-Sketch</h1>
    </header>
    <div class="grid-size">
        <button class="btn-set-grid-size">Set Grid Size</button>
        <input type="text" id="grid-size">
    </div>
    <p id="error-message">Error! Please, enter a number that is less or equal to 50!</p>
    <main class="main-content">
        <div class="settings">
            <div class="div-pen-color">
                <label for="pen-color" class="label-custom-color" id="label-pen-color">Pen Color</label>
                <input type="color" id="input-pen-color" class="input-custom-color">
            </div>
            <div class="div-background-color">
                <label for="background-color" class="label-custom-color" id="label-background-color">Background
                    Color</label>
                <input type="color" id="input-background-color" class="input-custom-color">
            </div>
            <button id="btn-black">Black</button>
            <button id="btn-rainbow">Rainbow</button>
            <button id="btn-opacity">Opacity</button>
            <button id="btn-eraser">Eraser</button>
            <button id="btn-clear">Clear</button>
        </div>
        <div class="grid"></div>
    </main>
</body>

</html>

CSS

:root {
  --grid-cols: 1;
  --grid-rows: 1;
}

* {
  margin: 0;
}

header {
  text-align: center;
  padding: 20px;
}

.main-content {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 95px;
  max-width: 1100px;
  margin: 0 auto;
}

.grid {
  display: grid;
  text-align: center;
  width: 500px;
  height: 500px;
  border: 5px solid black;
  grid-template-rows: repeat(var(--grid-rows), 1fr);
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  margin-right: auto;
}

.grid-item {
  display: grid;
  border: 1px solid black;
  transition: 0.3s ease-in-out;
  margin: 0px;
}

.grid-size {
  display: flex;
  justify-content: center;
  align-items: center;
}

label {
  margin-right: 5px;
}

.settings {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 30px;
  width: 200px;
}

#error-message {
  text-align: center;
  color: #ff0000;
  opacity: 0;
  margin: 10px;
}

.div-pen-color,
.div-background-color {
  display: flex;
  justify-content: center;
  align-items: center;
}

JavaScript

const body = document.querySelector("body");
const grid = document.querySelector(".grid");
const penCustomColor = document.querySelector("#input-pen-color");
const backgroundCustomColor = document.querySelector("#input-background-color");

let isMouseDown = false;
let currentTool = "black"; // 默认激活黑色笔工具

document.body.onmousedown = () => (isMouseDown = true);
document.body.onmouseup = () => (isMouseDown = false);

// 初始化工具按钮切换事件
function initToolButtons() {
  document.querySelector("#btn-black").addEventListener("click", () => {
    currentTool = "black";
  });

  document.querySelector("#btn-rainbow").addEventListener("click", () => {
    currentTool = "rainbow";
  });

  document.querySelector("#btn-opacity").addEventListener("click", () => {
    currentTool = "opacity";
  });

  document.querySelector("#btn-eraser").addEventListener("click", () => {
    currentTool = "eraser";
  });

  // 自定义笔色选择后切换到自定义笔工具
  penCustomColor.addEventListener("input", () => {
    currentTool = "customPen";
  });
}

// 初始化背景色设置事件
function initBackgroundColor() {
  backgroundCustomColor.addEventListener("input", () => {
    grid.style.backgroundColor = backgroundCustomColor.value;
  });
}

// 处理单元格绘制逻辑
function handleCellDraw(cell) {
  cell.addEventListener("mouseenter", () => {
    if (!isMouseDown) return;

    switch (currentTool) {
      case "black":
        cell.style.backgroundColor = "black";
        cell.dataset.opacity = "1";
        break;
      case "rainbow":
        const rainbowColors = ["#9400D3", "#4B0082", "#0000FF", "#00FF00", "#FFFF00", "#FF7F00", "#FF0000"];
        const randomColor = rainbowColors[Math.floor(Math.random() * rainbowColors.length)];
        cell.style.backgroundColor = randomColor;
        cell.dataset.opacity = "1";
        break;
      case "opacity":
        // 从自定义属性获取当前透明度,默认0
        let currentOpacity = parseFloat(cell.dataset.opacity) || 0;
        if (currentOpacity < 1) {
          currentOpacity += 0.1;
          cell.style.backgroundColor = `rgba(0, 0, 0, ${currentOpacity.toFixed(1)})`;
          cell.dataset.opacity = currentOpacity.toFixed(1);
        }
        break;
      case "eraser":
        cell.style.backgroundColor = "";
        cell.dataset.opacity = "0";
        break;
      case "customPen":
        cell.style.backgroundColor = penCustomColor.value;
        cell.dataset.opacity = "1";
        break;
    }
  });
}

function makeGrid(rows, columns) {
  grid.style.setProperty("--grid-rows", rows);
  grid.style.setProperty("--grid-cols", columns);
  for (let i = 0; i < rows * columns; i++) {
    let cell = document.createElement("div");
    cell.className = "grid-item";
    cell.dataset.opacity = "0"; // 初始化透明度记录属性
    grid.appendChild(cell);
    handleCellDraw(cell);
  }
}

// 初始化Clear按钮事件
function initClearButton() {
  const buttonClear = document.querySelector("#btn-clear");
  buttonClear.addEventListener("click", () => {
    grid.childNodes.forEach((child) => {
      child.style.backgroundColor = ""; // 清空单元格背景,透出Grid背景
      child.dataset.opacity = "0";
    });
  });
}

// 初始化新网格创建功能
function createNewGrid() {
  let inputValue = document.querySelector("#grid-size");
  let rows = 15;
  let columns = 15;

  inputValue.addEventListener("input", () => {
    rows = parseInt(inputValue.value);
    columns = parseInt(inputValue.value);
  });

  const buttonNewGrid = document.querySelector(".btn-set-grid-size");
  const errorMessage = document.querySelector("#error-message");
  buttonNewGrid.addEventListener("click", () => {
    document.querySelectorAll(".grid-item").forEach((e) => e.remove());
    if (!isNaN(rows) && rows <= 50) {
      errorMessage.style.opacity = 0;
      makeGrid(rows, columns);
      inputValue.value = "";
    } else {
      errorMessage.style.opacity = 1;
      errorMessage.style.transition = "0.3s ease-in-out";
      inputValue.value = "";
    }
  });
}

// 启动所有功能
initToolButtons();
initBackgroundColor();
makeGrid(15, 15);
initClearButton();
createNewGrid();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:15:26