So i need to create an infite grid and can draw image per tile with mouse click like this page, what is the idea here to make it? https://playgameoflife.com/
i tried the answer in the How can I make infinite grid with canvas? but it just a fake grid with limited wide and high
const init_infgrid = () => {
canvas_infgrid = $c('canvas');
canvas_infgrid.width = window.innerWidth;
canvas_infgrid.height = window.innerHeight;
c_infgrid = canvas_infgrid.getContext('2d');
canvas_infgrid.addEventListener("mousedown", e => {
reset();
start_infgrid = getPos_Infgrid(e)
});
canvas_infgrid.addEventListener("mouseup", reset);
canvas_infgrid.addEventListener("mouseleave", reset);
canvas_infgrid.addEventListener("mousemove", e => {
if (!start_infgrid) return;
let pos = getPos_Infgrid(e);
c_infgrid.translate(pos.x - start_infgrid.x, pos.y - start_infgrid.y);
draw();
start_infgrid = pos;
});
$('#canvasarea').appendChild(canvas_infgrid)
draw()
}
function draw() {
let step = 50;
let left = 0.5 - Math.ceil(canvas_infgrid.width / step) * step;
let top = 0.5 - Math.ceil(canvas_infgrid.height / step) * step;
let right = 2 * canvas_infgrid.width;
let bottom = 2 * canvas_infgrid.height;
c_infgrid.clearRect(left, top, right - left, bottom - top);
c_infgrid.beginPath();
for (let x = left; x < right; x += step) {
c_infgrid.moveTo(x, top);
c_infgrid.lineTo(x, bottom);
}
for (let y = top; y < bottom; y += step) {
c_infgrid.moveTo(left, y);
c_infgrid.lineTo(right, y);
}
c_infgrid.strokeStyle = "#888";
c_infgrid.stroke();
}
// Mouse event handling:
let start_infgrid;
const getPos_Infgrid = (e) => ({
x: e.clientX - canvas_infgrid.offsetLeft,
y: e.clientY - canvas_infgrid.offsetTop
});
const reset = () => {
start_infgrid = null;
//no want to reset translation
//c_infgrid.setTransform(1, 0, 0, 1, 0, 0); // reset translation
draw();
}
Here's what you can do:
Note: I copied over the snippet from the previous answer to modify. Credits to trincot.
let canvas = document.querySelector('.field');
let ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let offset = { x: 0, y: 0 }
const step = 10;
const blocks = [ [ 0, 0 ], [10, 20] ];
function draw() {
let left = 0.5 - Math.ceil(canvas.width / step) * step;
let top = 0.5 - Math.ceil(canvas.height / step) * step;
let right = 2*canvas.width;
let bottom = 2*canvas.height;
ctx.clearRect(left, top, right - left, bottom - top);
ctx.beginPath();
for (let x = left; x < right; x += step) {
ctx.moveTo(x, top);
ctx.lineTo(x, bottom);
}
for (let y = top; y < bottom; y += step) {
ctx.moveTo(left, y);
ctx.lineTo(right, y);
}
ctx.strokeStyle = "#888";
ctx.stroke();
// Draw blocks
for (const [ x, y ] of blocks) {
ctx.fillRect(
x * step + offset.x,
y * step + offset.y,
step,
step
);
}
}
// Mouse event handling:
let start;
const getPos = (e) => ({
x: e.clientX - canvas.offsetLeft,
y: e.clientY - canvas.offsetTop
});
const reset = () => {
start = null;
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset translation
draw();
}
canvas.addEventListener("mousedown", e => {
reset();
start = getPos(e)
});
canvas.addEventListener("mouseup", e => {
let pos = getPos(e);
const t = ctx.getTransform();
if (t.e === 0 & t.f === 0) {
const block = [
Math.floor((pos.x - offset.x) / step),
Math.floor((pos.y - offset.y) / step)
];
blocks.push(block);
} else {
offset.x += Math.floor(t.e / step) * step;
offset.y += Math.floor(t.f / step) * step;
}
reset();
});
canvas.addEventListener("mouseleave", reset);
canvas.addEventListener("mousemove", e => {
// Only move the grid when we registered a mousedown event
if (!start) return;
let pos = getPos(e);
// Move coordinate system in the same way as the cursor
ctx.translate(pos.x - start.x, pos.y - start.y);
draw();
start = pos;
});
draw(); // on page load
body, html {
width: 100%;
height: 100%;
margin: 0;
padding:0;
overflow:hidden;
}
canvas { background: silver; }
<canvas class="field"></canvas>