Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Canvas Draw lines not appearing

I’m creating a hex based map generator and as part of that I am trying to – on the client side – draw "rivers", lines that travel through the centres of the hexes that the server end calculates have rivers.

Here are the relevant variables (this works it gets values inserted by django from the server end I’ve tested it it all works fine)

       // The optional populators
        const rivers = {{ rivers |safe}};
        const cities = {{ cities |safe}};
        const roads = {{roads |safe}};

        // Constants for our angles and scales, starting with scale 5
        const a = Math.PI/3;
        var r = 5;

And here is the function that draws the rivers

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

        // Function that draws Rivers
        function DrawRivers(){
            // For each river in the rivers
            for (var river of rivers) {
                // Set up point tracking
                let x_coord = r + river[0][0] * (r + (r * Math.cos(a)));
                let y_coord = r + river[0][1] * (r + (r*Math.sin(a)));
                if (river[0][0] % 2 == 1) {
                    y_off = y_coord;
                } else { // If it's an even number of tiles in the row it'll be the lower part
                    y_off = y_coord + r * Math.sin(a);
                }

                ctx.beginPath();
                ctx.lineWidth = r;
                ctx.strokeStyle = "#000000";
                ctx.moveTo(x_coord, Math.round(y_off))
                // For each point in the river
                for (var river_hex of river){
                    let x_coord = r + river[0][0] * (r + (r * Math.cos(a)));
                    let y_coord = r + river[0][1] * (r + (r*Math.sin(a)));
                    if (river[0][0] % 2 == 1) {
                        y_off = y_coord;
                    } else { // If it's an even number of tiles in the row it'll be the lower part
                        y_off = y_coord + r * Math.sin(a);
                    }
                    ctx.lineTo(x_coord, Math.round(y_off))
                }
                ctx.closePath();
                ctx.stroke();
                

            }
        }

However when I run this code the lines do not draw. I’ve stepped through the code and everything seems like it works; there aren’t any points where the code doesn’t have the required variables, it’s just when the ctx.stroke() command is called it doesn’t actually draw the line.

Can someone else see where I’ve gone wrong? Because I honestly can’t…

>Solution :

In your inner loop "For each point in the river" you are only using river[0], not river_hex (likely a copy-paste error), so you ended up drawing a single point.

You can simplify your code (and make less copy-paste mistakes 😉 ) by moving the hex-to-screen coordinate computation to a separate function, and by using an old-school for loop so you don’t need to handle the first moveTo separately.

const rivers = [
  [
    [0, 0],
    [1, 0],
    [1, 1],
    [1, 2],
    [1, 3],
    [1, 4],
    [2, 4],
    [3, 5],
    [4, 5],
  ],
];

const a = Math.PI / 3;
var r = 15;

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

function convertCoordinate(hex) {
  const [hexX, hexY] = hex;
  const x_coord = r + hexX * (r + (r * Math.cos(a)));
  let y_coord = r + hexY * (r + (r * Math.sin(a)));
  if (hexX % 2 !== 1) {
    // If it's an even number of tiles in the row it'll be the lower part
    y_coord += r * Math.sin(a);
  }
  return [x_coord, y_coord];
}

// Function that draws Rivers
function DrawRivers() {
  // For each river in the rivers
  for (var river of rivers) {
    ctx.lineWidth = r;
    ctx.strokeStyle = '#000000';
    ctx.beginPath();
    // For each point in the river
    for (let i = 0; i < river.length; i++) {
      const [x, y] = convertCoordinate(river[i]);
      if (i === 0) ctx.moveTo(x, y);
      else ctx.lineTo(x, y);
    }
    // Not quite sure if a river should be closed...
    // ctx.closePath();
    ctx.stroke();
  }
}

DrawRivers();
canvas {
  border: 1px solid orange;
}
<canvas id="canvas" width="500" height="500"></canvas>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading