【问题标题】:How to draw a grid onto the canvas?如何在画布上绘制网格?
【发布时间】:2020-10-22 05:08:21
【问题描述】:

所以我正在研究一种 javascript 中的寻路算法,为了好玩和练习,我需要一个网格,我试图让用户决定画布的宽度和高度,并让他们决定有多少列和网格具有使用提示方法的行。我有这段代码,它只绘制列而不是行,无论我给网站提供什么输入

let grid = {
  width: 0,
  height: 0,
}

grid.width = Number(prompt("how many columns do you want? don't type zero if you care about your computer's health"));
grid.height = Number(prompt("how many rows do you want? don't type zero if you care about your computer's health"));
const canvasWidth = Number(prompt("how many pixels wide do you want the screen? i recomend around 1000 but it depends on your computer (i think)"));
const canvasHeight = Number(prompt("how many pixels high do you want the screen? i recomend aroun 500 but it depends on your computer (i think)"));

let canvas = document.createElement("CANVAS");
let ctx = canvas.getContext("2d");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.border = "1px solid black"
ctx.beginPath();
ctx.lineWidth = 1;
ctx.lineStyle = "black";
for (let x = 0; x < canvasWidth; x += canvasWidth / grid.width) {
  ctx.moveTo(x, 0)
  ctx.lineTo(x, canvasHeight)
}
for (let y = 0; y < canvasHeight; y += canvasHeight / grid.heigth) {
  ctx.moveTo(0, y)
  ctx.lineTo(canvasWidth, y)
}
ctx.stroke();
document.body.appendChild(canvas);

【问题讨论】:

  • 我更新了下面回复的第一部分,以解决模糊线问题。

标签: javascript html dom


【解决方案1】:

for 循环根据它们绘制的线的方向使用了不正确的值。

应该是:

for(let x = 0; x < canvasHeight; x += canvasHeight / grid.height){
    ctx.moveTo(x, 0)
    ctx.lineTo(x, canvasHeight)
}
for(let y = 0; y < canvasWidth; y += canvasWidth / grid.width){
    ctx.moveTo(0, y)
    ctx.lineTo(canvasWidth, y)
}

试试这个:

let grid = {
    width:0,
    height:0,
}

grid.width = Number(prompt("how many columns do you want? don't type zero if you care about your computer's health"));
grid.height = Number(prompt("how many rows do you want? don't type zero if you care about your computer's health"));
const canvasWidth = Number(prompt("how many pixels wide do you want the screen? i recomend around 1000 but it depends on your computer (i think)"));
const canvasHeight = Number(prompt("how many pixels high do you want the screen? i recomend aroun 500 but it depends on your computer (i think)"));

let canvas = document.createElement("CANVAS");
let ctx = canvas.getContext("2d");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.border = "1px solid black"
ctx.beginPath();
ctx.lineWidth = 1;
ctx.lineStyle = "black";
for(let x = 0; x < canvasHeight; x += canvasHeight / grid.height){
    ctx.moveTo(x, 0)
    ctx.lineTo(x, canvasHeight)
}
for(let y = 0; y < canvasWidth; y += canvasWidth / grid.width){
    ctx.moveTo(0, y)
    ctx.lineTo(canvasWidth, y)
}
ctx.stroke();
document.body.appendChild(canvas);

【讨论】:

    【解决方案2】:

    我建议您像这样设置您的流程。它变得更具可读性并提供可扩展性。将用户定义的值作为选项传递给处理创建网格的函数。我为网格选项提供了一些默认值。

    另外,我建议在绘制到画布之前四舍五入您的偏移量。


    编辑:如果您注意到,您正在绘制模糊的线条。您可以通过(0.5, 0.5) 翻译上下文来轻松解决此问题。

    问:为什么 x 和 y 从 0.5 开始?为什么不是 0?

    见:http://diveintohtml5.info/canvas.html#paths

    const questions = [
      "How many columns do you want? Don't type zero if you care about your computer's health?",
      "How many rows do you want? Don't type zero if you care about your computer's health?",
      "How many pixels wide do you want the screen? I recommend around 1,000, but it depends on your computer (I think)?",
      "How many pixels high do you want the screen? I recommend around 500, but it depends on your computer (I think)?"
    ];
    
    const options = {
      cols   : Number(prompt(questions[0])) || 10,
      rows   : Number(prompt(questions[1])) || 10,
      width  : Number(prompt(questions[2])) || 100,
      height : Number(prompt(questions[3])) || 100
    };
    
    document.body.appendChild(createCanvasGrid(options));
    
    function createCanvasGrid(options) {
      let canvas = document.createElement("CANVAS");
      let ctx = canvas.getContext("2d");
    
      canvas.width = options.width;
      canvas.height = options.height;
      canvas.style.border = "1px solid red"
    
      ctx.translate(0.5, 0.5); // https://stackoverflow.com/a/13294650/1762224
    
      ctx.beginPath();
      ctx.lineWidth = 1;
      ctx.strokeStyle = "red";
    
      let offsetX = Math.floor(options.width / options.cols);
      let offsetY = Math.floor(options.height / options.rows);
    
      for (let x = offsetX; x < options.width; x += offsetX) {
        ctx.moveTo(x, 0);
        ctx.lineTo(x, options.height);
      }
      
      for (let y = offsetY; y < options.height; y += offsetY) {
        ctx.moveTo(0, y);
        ctx.lineTo(options.width, y);
      }
      
      ctx.stroke();
    
      return canvas;
    }

    高级示例

    这是一个可配置的高级示例。

    const DEFAULT_OPTIONS = {
      cols       : 10,
      rows       : 10,
      width      : 100,
      height     : 100,
      weight     : 1,
      background : null,
      color      : '#000000'
    };
    
    const main = () => {
      addGrid({
        width      : 150,
        height     : 150,
        background : '#183',
        color      : '#999'
      });
      
      addGrid({
        width      : 240,
        height     : 120,
        weight     : 2,
        color      : '#DDD'
      });
    }
    
    const addGrid = (options) => {
      document.body.appendChild(createCanvasGrid(options));
    };
    
    const createCanvasGrid = (options) => {
      let opts = Object.assign({}, DEFAULT_OPTIONS, options);
      let canvas = document.createElement("CANVAS");
      let ctx = canvas.getContext("2d");
    
      canvas.width = opts.width;
      canvas.height = opts.height;
      
      let weight2 = opts.weight * 2;
      let weightHalf = opts.weight / 2;
      
      let availWidth =  opts.width - opts.weight;
      let availHeight = opts.height - opts.weight;
      
      let cellWidth = availWidth / opts.cols;
      let cellHeight = availHeight / opts.rows;
    
      if (options.background) {
        ctx.fillStyle = opts.background;
        ctx.fillRect(0, 0, opts.width, opts.height);
      }
      
      ctx.beginPath();
      ctx.strokeStyle = opts.color;
      ctx.lineWidth = opts.weight;
      
      for (let col = 0; col <= opts.cols; col++) {
        let newX = Math.floor(col * cellWidth) + weightHalf;
        ctx.moveTo(newX, 0);
        ctx.lineTo(newX, opts.height);
      }
      
      for (let row = 0; row <= opts.rows; row++) {
        let newY = (row * cellHeight) + weightHalf;
        ctx.moveTo(0, newY);
        ctx.lineTo(opts.width, newY);
      }
      
      ctx.stroke();
    
      return canvas;
    };
    
    main();
    body {
      background: #222;
      margin: 0;
      padding: 0;
    }
    
    canvas {
      margin: 0.5em;
    }

    【讨论】:

    • 谢谢,你的代码比我的更有条理
    • @user12904234 我在下面添加了一个高级示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 2021-07-15
    • 2023-03-14
    相关资源
    最近更新 更多