需要帮助编写函数以使网格内的任何框都可单击并填充色轮

时间:2018-12-25 01:07:14

标签: javascript html5 function canvas

我正在从事像素艺术项目。我期望在这里做的是能够单击网格内的任何框,并使用颜色输入中的颜色对其进行渲染。

我设法了解了循环如何使用canvas和javascript创建网格。接下来,我创建了一个名为colorPicker()的函数,该函数使我可以单击任何网格单元并从颜色输入中获取值并将其呈现为该颜色。我使用了canvas.addEventListener("click", function(event) { ... }) 并传递了值为xCoordyCoord的变量event.xevent.y。这使我可以返回在网格内部单击时的鼠标位置。

我现在遇到的问题是,我在网格上绘制的所有400个图仅渲染了1个正方形。渲染有效,只是我只能单击一个框并从输入中渲染其颜色。

有人能使用我目前拥有的javascript逻辑为我提供一些解决该功能的帮助吗?

var title = document.getElementById("title");
var canvas = document.getElementById("canvas");
var color = document.getElementById("color");
var btn = document.getElementById("btn");
var ctx = canvas.getContext("2d");

// The function that draws the grid     
function drawGrid() {
  ctx.fillStyle = "#009EFF";
  ctx.fillRect(0, 0, 400, 400);
  ctx.strokeStyle = "black";
  ctx.lineWidth = 1;

  // The for loop that draws the x-axis
  for (x = 0; x <= 400; x += 20) {
    ctx.moveTo(x, 0);
    ctx.lineTo(x, 400);
    ctx.stroke();
  }

  // The for loop that draws the y-axis
  for (y = 0; y <= 400; y += 20) {
    ctx.moveTo(0, y);
    ctx.lineTo(400, y);
    ctx.stroke();
  }
}

drawGrid();

// Function that clicks and fill grid boxes w / color
function colorPicker() {
  canvas.addEventListener("click", function(event) {
    var newColor = color.value;
    ctx.fillStyle = newColor;
    xCoord = event.x;
    yCoord = event.y;
    ctx.fillRect(0, 0, 20, 20);

    console.log(xCoord, yCoord);
    console.log(newColor);
  });
}

colorPicker();
#canvas {
  border: 1px solid black;
  background-size: 100%;
  display: block;
  margin-top: 50px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 0;
  padding-right: 0;
}
<div class="color-wheel">
  Color: <input type="color" id="color" />
</div>

<canvas id="canvas" width="400" height="400"></canvas>

1 个答案:

答案 0 :(得分:2)

您的问题是这一行:

ctx.fillRect(0, 0, 20, 20);

您不会在每次点击时仅填充左上方的单元格,而是填充了点击的单元格。

当您应该从光标计算此位置时,当前仅在这里使用(0,0)。尽管画布和光标使用的坐标不同,所以您需要编写一个转换函数:

function mousePosToCanvasPos(mouseX, mouseY) {
  var canvasPos = canvas.getBoundingClientRect();

  return {
    x: Math.floor((mouseX - canvasPos.x) / 20) * 20,
    y: Math.floor((mouseY - canvasPos.y) / 20) * 20,
  };
}

mousePosToCanvasPos()函数获取画布的当前渲染位置(canvasPos),并计算光标相对于画布左上角的偏移量(mouse_ - canvasPos._)。然后将其向下舍入到最接近的20的倍数,以返回所单击的单元格(Math.floor((mouse_ - canvasPos._) / 20) * 20)的左上角。如果您将像元大小更改为20以外的值,请务必在此功能中也将其更改。或者更好的是提取常数(var cellSize = 20)。

将此功能添加到您的代码中将为我们提供:

var title = document.getElementById("title");
var canvas = document.getElementById("canvas");
var color = document.getElementById("color");
var btn = document.getElementById("btn");
var ctx = canvas.getContext("2d");

// The function that draws the grid     
function drawGrid() {
  ctx.fillStyle = "#009EFF";
  ctx.fillRect(0, 0, 400, 400);
  ctx.strokeStyle = "black";
  ctx.lineWidth = 1;

  // The for loop that draws the x-axis
  for (x = 0; x <= 400; x += 20) {
    ctx.moveTo(x, 0);
    ctx.lineTo(x, 400);
    ctx.stroke();
  }

  // The for loop that draws the y-axis
  for (y = 0; y <= 400; y += 20) {
    ctx.moveTo(0, y);
    ctx.lineTo(400, y);
    ctx.stroke();
  }
}

drawGrid();

function mousePosToCanvasPos(mouseX, mouseY) {
  var canvasPos = canvas.getBoundingClientRect();

  return {
    x: Math.floor((mouseX - canvasPos.x) / 20) * 20,
    y: Math.floor((mouseY - canvasPos.y) / 20) * 20,
  };
}

// Function that clicks and fill grid boxes w / color
function colorPicker() {
  canvas.addEventListener("click", function(event) {
    var newColor = color.value;
    ctx.fillStyle = newColor;

    var canvasCellPos = mousePosToCanvasPos(event.x, event.y);
    ctx.fillRect(canvasCellPos.x, canvasCellPos.y, 20, 20);

    console.log(event.x, event.y);
    console.log(newColor);
  });
}

colorPicker();
#canvas {
  border: 1px solid black;
  background-size: 100%;
  display: block;
  margin-top: 50px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 0;
  padding-right: 0;
}
<div class="color-wheel">
  Color: <input type="color" id="color" />
</div>

<canvas id="canvas" width="400" height="400"></canvas>

您会注意到这里有些东西还不太正确:每次填充单元格时,它的边框都会变细。要解决此问题,您需要从fillRect的每一侧移除一个像素:

ctx.fillRect(canvasCellPos.x + 1, canvasCellPos.y + 1, 18, 18);

var title = document.getElementById("title");
var canvas = document.getElementById("canvas");
var color = document.getElementById("color");
var btn = document.getElementById("btn");
var ctx = canvas.getContext("2d");

// The function that draws the grid     
function drawGrid() {
  ctx.fillStyle = "#009EFF";
  ctx.fillRect(0, 0, 400, 400);
  ctx.strokeStyle = "black";
  ctx.lineWidth = 1;

  // The for loop that draws the x-axis
  for (x = 0; x <= 400; x += 20) {
    ctx.moveTo(x, 0);
    ctx.lineTo(x, 400);
    ctx.stroke();
  }

  // The for loop that draws the y-axis
  for (y = 0; y <= 400; y += 20) {
    ctx.moveTo(0, y);
    ctx.lineTo(400, y);
    ctx.stroke();
  }
}

drawGrid();

function mousePosToCanvasPos(mouseX, mouseY) {
  var canvasPos = canvas.getBoundingClientRect();

  return {
    x: Math.floor((mouseX - canvasPos.x) / 20) * 20,
    y: Math.floor((mouseY - canvasPos.y) / 20) * 20,
  };
}

// Function that clicks and fill grid boxes w / color
function colorPicker() {
  canvas.addEventListener("click", function(event) {
    var newColor = color.value;
    ctx.fillStyle = newColor;

    var canvasCellPos = mousePosToCanvasPos(event.x, event.y);
    ctx.fillRect(canvasCellPos.x + 1, canvasCellPos.y + 1, 18, 18);

    console.log(event.x, event.y);
    console.log(newColor);
  });
}

colorPicker();
#canvas {
  border: 1px solid black;
  background-size: 100%;
  display: block;
  margin-top: 50px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 0;
  padding-right: 0;
}
<div class="color-wheel">
  Color: <input type="color" id="color" />
</div>

<canvas id="canvas" width="400" height="400"></canvas>