【问题标题】:JavaScript to change backgroundColor of grid cell on ClickJavaScript 在单击时更改网格单元格的背景颜色
【发布时间】:2021-01-04 00:07:12
【问题描述】:

我的基本 HTML 如下:

<!DOCTYPE html>
<html>
<head>
    <title>Art Maker!</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>Pixel Art</h1>

    <h2>Choose Grid Size</h2>
    <form id="sizePicker">
        Grid Height:
        <input type="number" id="inputHeight" name="height" min="1" value="1">
        Grid Width:
        <input type="number" id="inputWidth" name="width" min="1" value="1">
        <input type="submit">
    </form>

    <h2>Pick A Color</h2>
    <input type="color" id="colorPicker">

    <h2>Design Canvas</h2>
    <table id="pixelCanvas"></table>

    <script src="designs.js"></script>
</body>
</html>

以下 JavaScript 用于:

  1. 获取用户输入:高度和宽度
  2. 根据高度和宽度绘制网格
  3. 获取 HTML 颜色选择器
  4. 当用户单击单元格时,根据步骤 (3) 使用背景颜色填充单元格

我卡在第 (4) 步。我创建了一个函数 respondToClick(event) 并使用 eventListener 将它附加到 tblRow。 “单击”时应使用背景颜色填充单元格;但事实并非如此。请指教哪里出了问题。

//获取网格大小值;高度和宽度

let height = document.getElementById('inputHeight').value;

let width = document.getElementById('inputWidth').value;

const gridHeight = document.getElementById('inputHeight');

gridHeight.addEventListener("input", function() {
  height = document.getElementById('inputHeight').value;
})

const gridWidth = document.getElementById('inputWidth');

gridWidth.addEventListener("input", function() {
  width = document.getElementById('inputWidth').value;
})

/ 创建画布的函数

const table = document.getElementById('pixelCanvas');

function createCanvas(event) {
  
  for (let h = 1; h <= height; h++) {
    const row = document.createElement('tr');
    
    for (let w = 1; w <= width; w++) {
      const cell = document.createElement('td');
      
      cell.style.cssText = "height: 15px; width: 15px";
      row.appendChild(cell);
    }
    
    table.appendChild(row);
  }  
}

const form = document.querySelector('form');

// 将 createCanvas() 绑定到“提交”

form.addEventListener('submit', createCanvas);

// 更新颜色的事件监听器

let color = document.getElementById('colorPicker').value;

document.getElementById('colorPicker').onchange = function() {
  color = this.value;
}

// 仅当用户点击时激活功能

function respondToClick(event) {
  if (event.target.nodeName.toLowerCase() === 'td') {
    event.target.style.backgroundColor = color;
  }
}

const tblRow = document.getElementsByTagName('tr');

tblRow.forEach(row => function() {
  row.addEventListener("click", respondToClick);
});

【问题讨论】:

  • 控制台是否出现任何错误?

标签: javascript


【解决方案1】:

几个问题

  • 您应该在创建rows 后绑定点击处理程序,因为您绑定到tr。或者更好的是,既然您已经委托了事件,请使用 table 元素来绑定处理程序,因为它从一开始就在那里。
  • 您需要阻止表单实际提交(导致页面重新加载
  • 创建新画布时需要清除画布

// obtain grid size value; height & width

const gridHeight = document.getElementById('inputHeight');
const gridWidth = document.getElementById('inputWidth');

let height = gridHeight.value;
let width = gridWidth.value;

gridHeight.addEventListener("input", function() {
  height = document.getElementById('inputHeight').value;
})

gridWidth.addEventListener("input", function() {
  width = document.getElementById('inputWidth').value;
})

const table = document.getElementById('pixelCanvas');

function createCanvas(event) {
  event.preventDefault();
  table.innerHTML = '';
  for (let h = 1; h <= height; h++) {
    const row = document.createElement('tr');

    for (let w = 1; w <= width; w++) {
      const cell = document.createElement('td');
      row.appendChild(cell);
    }
    table.appendChild(row);
  }
}

const form = document.querySelector('form');

// bind createCanvas() to "submit"
form.addEventListener('submit', createCanvas);

// event listener to update color
const picker = document.getElementById('colorPicker')
let color = picker.value;

picker.onchange = function() {
  color = this.value;
}

// function activated when user click on only

function respondToClick(event) {
  if (event.target.nodeName.toLowerCase() === 'td') {
    event.target.style.backgroundColor = color;
  }
}

table.addEventListener("click", respondToClick);
table {
  border: 1px solid black;
 }
 
 td{
 width:15px;
 height:15px;
 overflow:hidden;
 }
<h1>Pixel Art</h1>

<h2>Choose Grid Size</h2>
<form id="sizePicker">
  Grid Height:
  <input type="number" id="inputHeight" name="height" min="1" value="1"> Grid Width:
  <input type="number" id="inputWidth" name="width" min="1" value="1">
  <input type="submit">
</form>

<h2>Pick A Color</h2>
<input type="color" id="colorPicker">

<h2>Design Canvas</h2>
<table id="pixelCanvas" cellspacing="0" cellpadding="0"></table>

【讨论】:

  • 另一个您错过的问题是您绝对应该在输入字段中使用label。这样你就知道在哪里输入哪个值了。
  • @cloned,是的,这是一种很好的做法,但与非工作代码无关:)
【解决方案2】:

以下是代码中的问题:

  • document.getElementsByTagName(...) 返回一个HTMLCollection,您不能在其上调用.forEach() 方法。而是使用document.querySelectorAll(...),它返回一个NodeList,它有一个名为.forEach()的方法。

    const tblRow = document.querySelectorAll('tr');
    
  • 您需要使用Event.preventDefault() 防止submit 事件的默认行为

    function createCanvas(event) {
       event.preventDefault();    
       ...
    }
    
  • 由于您在document.getElementsByTagName('tr') 返回的HTMLCollection 上调用了.forEach() 方法,因此出现错误并且没有在任何tr 元素上添加事件侦听器。

    您可以利用Event Bubbling 并在table 元素上添加事件侦听器,而不是在每个tr 元素上添加click 事件侦听器。

    table.addEventListener("click", respondToClick);
    

以下代码 sn -p 显示固定代码示例:

let height = document.getElementById('inputHeight').value;
let width = document.getElementById('inputWidth').value;
const gridHeight = document.getElementById('inputHeight');
const gridWidth = document.getElementById('inputWidth');
const table = document.getElementById('pixelCanvas');
const form = document.querySelector('form');
const colorPicker = document.getElementById('colorPicker');
let color = colorPicker.value;

gridHeight.addEventListener("input", function() {
  height = document.getElementById('inputHeight').value;
})

gridWidth.addEventListener("input", function() {
  width = document.getElementById('inputWidth').value;
})

function createCanvas(event) {
  event.preventDefault();

  for (let h = 1; h <= height; h++) {
    const row = document.createElement('tr');

    for (let w = 1; w <= width; w++) {
      const cell = document.createElement('td');
      row.appendChild(cell);
    }

    table.appendChild(row);
  }
}

form.addEventListener('submit', createCanvas);

colorPicker.addEventListener('change', function() {
  color = this.value;
});

function respondToClick(event) {
  if (event.target.matches('td')) {
    event.target.style.backgroundColor = color;
  }
}

table.addEventListener("click", respondToClick);
table,
tr,
td {
  border: 1px solid;
  border-collapse: collapse;
  ;
}

td {
  width: 30px;
  height: 30px;
}
<h1>Pixel Art</h1>

<h2>Choose Grid Size</h2>
<form id="sizePicker">
  Grid Height:
  <input type="number" id="inputHeight" name="height" min="1" value="1" /> Grid Width:
  <input type="number" id="inputWidth" name="width" min="1" value="1" />
  <input type="submit" />
</form>

<h2>Pick A Color</h2>
<input type="color" id="colorPicker" />

<h2>Design Canvas</h2>
<table id="pixelCanvas"></table>

旁注:responseToClick() 事件处理程序中,您有以下代码行:

cell.style.cssText = "height: 15px; width: 15px";

虽然这样可行,但最好在 CSS 中定义这些样式。我在上面的代码sn-p中做了同样的事情。

还有一点需要注意的是,在修复了上面代码sn-p所示的代码之后,你可能想在创建新的之前删除之前创建的表格内容。如果这是您想要做的,那么您可以通过将table 元素的.innerHTML 设置为createCanvas() 事件处理程序中的空字符串来实现。

【讨论】:

  • 感谢您的建议。实际上我知道使用 CSS 来设置表格、行和单元格的样式更容易。我故意想练习 JavaScript,因此我尝试用 JavaScript 做所有事情。只是对您的观点感到好奇...在 responseToClick 事件处理程序中添加 table.innerHTML = "" 。如何清除表格内容?事实上,这是下一步。我将 table.innerHTML = "" 放在 createCanvas 中,就在 event.preventDefault() 之后。它确实清除了表格内容。我也想知道,表格创建完成后点击单元格,怎么用JS找出背景颜色?
  • 其实table.innerHTML = ''应该在createCanvas()函数里面。这是我的答案中的一个错误,现在已修复。就您的第二个问题而言,我不明白您在说如何使用JS 找出背景颜色? 时要问什么。背景颜色是什么?
  • 好的,感谢您澄清这一点。好的,让我更具体一点。单击单元格后,将为单元格分配背景颜色。在这种情况下,我如何使用 JavaScript 来找出表格中的任何单元格是否具有特定的背景颜色?例如,我单击表格中的一个单元格,该单元格被填充为蓝色。如何列出该单元格的背景颜色?或检索表/行并列出背景颜色?
  • 您可以选择table 中的所有td 元素,然后遍历集合并使用Window.getComputedStyle() 获取任何td 元素上的样式。
猜你喜欢
  • 2016-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
相关资源
最近更新 更多