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

etch-a-sketch项目如何实现鼠标按下后触发mouseover变色效果

Etch-a-Sketch 按住鼠标触发绘制实现方案

问题背景

开发The Odin Project的etch-a-sketch项目时,原有交互为鼠标悬停网格元素即触发颜色变化,需要调整为仅按住鼠标左键状态下,鼠标悬停网格才触发变色绘制,匹配常规画板拖拽绘制的交互逻辑。

核心实现逻辑

通过全局状态变量标记鼠标左键的按下状态,仅在状态为按下时执行变色逻辑:

  • 全局监听鼠标按下、松开事件,更新状态标记
  • 网格的悬停变色逻辑增加状态判断,非按下状态直接终止执行
  • 补充网格点击即上色的逻辑,优化单点绘制体验
  • 修复原有代码中多元素共用同个id的规范问题

具体代码修改步骤

1. 新增全局状态变量

在JS文件顶部的变量声明区域,添加鼠标状态标记:

let isMouseDown = false; // 标记鼠标左键是否处于按下状态

2. 绑定全局鼠标状态监听

在createGrid()函数调用前,添加全局事件监听,同步鼠标按下/松开状态,同时阻止浏览器默认拖拽选中的干扰行为:

// 监听鼠标左键按下
document.addEventListener('mousedown', (e) => {
  if (e.button === 0) isMouseDown = true;
})
// 监听鼠标左键松开
document.addEventListener('mouseup', (e) => {
  if (e.button === 0) isMouseDown = false;
})
// 阻止原生拖拽选中文本的默认行为,避免绘制干扰
document.addEventListener('dragstart', (e) => e.preventDefault())

3. 修改变色函数增加状态判断

在changeColor函数最开头添加状态校验,非按下状态直接返回,不执行变色逻辑:

function changeColor(e) {
  // 鼠标未按下时直接终止逻辑
  if (!isMouseDown) return;

  // 下方保留原有所有变色逻辑,无需修改
  if (mode === 'pencil') {
    e.target.classList.add('black');
    e.target.classList.remove('white');
    e.target.style.backgroundColor = null;
    e.target.style.opacity = null;
  } else if (mode === 'rainbow') {
    const green = Math.floor(Math.random() * 250);
    const blue = Math.floor(Math.random() * 250);
    const red = Math.floor(Math.random() * 250);
    e.target.style.backgroundColor = `rgb(${red}, ${green}, ${blue})`;
    e.target.style.opacity = null;
  } else if (mode === 'erase') {
    e.target.classList.add('white');
    e.target.style.backgroundColor = null;
    e.target.style.opacity = null;
  } else if (mode === 'pickColor') {
    e.target.style.backgroundColor = pickColor.value;
    e.target.style.opacity = null;
  } else if (mode === 'shading') {
    e.target.classList.remove('white');
    e.target.classList.add('black');
    e.target.style.opacity = Number(e.target.style.opacity) + 0.2;
  } else {
    e.target.classList.add('black')
  }
}

4. 调整网格创建逻辑

修改createGrid函数,将重复的id改为符合规范的class,同时给网格添加鼠标按下即触发变色的事件,优化单点点击绘制体验:

function createGrid(size) {
  size = gridSize.value;
  container.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
  container.style.gridTemplateRows = `repeat(${size}, 1fr)`;
  for (let i = 0; i < size * size; i++) {
    const grid = document.createElement('div');
    // 原id="grid"改为class,id需全局唯一,多元素同类样式用class
    grid.classList.add('grid');
    container.appendChild(grid);
    grid.addEventListener('mouseover', changeColor);
    // 新增:鼠标直接点击网格时也触发变色
    grid.addEventListener('mousedown', changeColor);
  }
}

5. 同步修改CSS选择器

将CSS中原有的#grid选择器改为.grid,匹配刚才的class修改,保证网格样式正常生效:

.grid {
  border: none;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:30:52