How to Get the Grid Coordinates of an Element Using JavaScript

How to get the grid coordinates of an element using JavaScript?

//Add click event for any child div of div = grid
$(document).ready(function(){
$('.grid').on('click', 'div', function(e){
GetGridElementsPosition($(this).index()); //Pass in the index of the clicked div
//Relevant to its siblings, in other words if this is the 5th div in the div = grid
});
});

function GetGridElementsPosition(index){
//Get the css attribute grid-template-columns from the css of class grid
//split on whitespace and get the length, this will give you how many columns
const colCount = $('.grid').css('grid-template-columns').split(' ').length;

const rowPosition = Math.floor(index / colCount);
const colPosition = index % colCount;

//Return an object with properties row and column
return { row: rowPosition, column: colPosition } ;
}

How to get grid coordinates which has some empty cells in javascript?

This snippet parses the computed styles of the grid container to determine the amount and size of the rows and columns. It creates two arrays of top left row and column positions.

It then checks for a given element if the offsetTop and offsetLeft of a given element is within the coordinates of each row and column. With it it determines the position on the grid.

It returns an object with the row, column, x and y values. All values are in relation to the grid element.

const container = document.getElementById('GridContainer');

const getPositionInGrid = (element, grid) => {
const gridStyles = getComputedStyle(grid);
const display = gridStyles.getPropertyValue('display');
if (display !== 'grid') {
throw new Error('grid element does not have display value of grid;');
}

const rows = gridStyles.getPropertyValue('grid-template-rows').split(' ');
const columns = gridStyles.getPropertyValue('grid-template-columns').split(' ');
const gap = parseInt(gridStyles.getPropertyValue('grid-gap'));

const rowPositions = rows.map((row, i) => {
const rowPosition = parseInt(row);
return !i ? 0 : (rowPosition + gap) * i;
});

const columnPositions = columns.map((column, i) => {
const columnPosition = parseInt(column);
return !i ? 0 : (columnPosition + gap) * i;
});

const {
offsetTop,
offsetLeft
} = element;

let row = null;
rowPositions.forEach((position, i) => {
const nextRow = rowPositions[i + 1];
if ((!nextRow && row === null) || (offsetTop >= position && offsetTop < nextRow)) {
row = i + 1;
}
});

let column = null;
columnPositions.forEach((position, i) => {
const nextColumn = columnPositions[i + 1];
if ((!nextColumn && column === null) || (offsetLeft >= position && offsetLeft < nextColumn)) {
column = i + 1;
}
});

return { row, column, y: offsetTop, x: offsetLeft};
};

container.addEventListener('click', event => {
const {
target
} = event;
if (target.classList.contains('item')) {
const {
row,
column,
x,
y
} = getPositionInGrid(target, container);
console.log('Row:', `${row},`, 'Column:', column, '|', 'x:', `${x},`, 'y:', y);
}
});
#GridContainer {
width: 65vw;
height: 80vh;
margin: 8vh auto 0 auto;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 10px;
position: relative;
}

.column1 {
grid-column-start: 2;
}

.item {
background-color: red;
}

.column0 {
grid-column-start: 1;
}
<div id="GridContainer">
<div class="item row1 column1"></div>
<div class="item row1 column2"></div>
<div class="item row1 column3"></div>
<div class="item row2 column0"></div>
<div class="item row2 column1"></div>
<div class="item row2 column2"></div>
<div class="item row2 column3"></div>
<div class="item row3 column1"></div>
<div class="item row3 column2"></div>
<div class="item row3 column3"></div>
<div class="item row3 column4"></div>
</div>

Getting X and Y coordinates with the cell number in a grid

A nested for loop would solve this. First loop through all the rows, then through the columns of each row. y will indicate the current row and x the current column.

Check for a match within the second loop. If a match is found, then return an object with the x and y coordinates in an object.

const grid = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]
];

const rows = grid.length;
const columns = grid[0].length;

function getXYCoords(grid, cell) {
for (let y = 0; y < rows; y++) {
for (let x = 0; x < columns; x++) {
if (grid[y][x] === cell) {
return ({x, y});
}
}
}
return null;
}

console.log(getXYCoords(grid, 8))
console.log(getXYCoords(grid, 19))
console.log(getXYCoords(grid, 22))

How to find the center coords of each cell in the following grid?

I don't get the swapping of the z and y but here's a way to get the array you want. Keep in mind I didn't know how you grid was being created so I used a ES6 class and captured each cells center point. Then I just pushed them to an array while swapping the y and z.

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 250;
canvas.height = 250;
let cellSize = 50;
let grid = [];
let centerPoints = [];

class Cell {
constructor(x, y) {
this.x = x;
this.y = y;
this.z = 0;
this.width = cellSize;
this.height = cellSize;
this.c = "black";
this.center = { x: this.x + this.width / 2 - canvas.width/2, y: this.y + this.height / 2 - canvas.height/2};
}
draw() {
ctx.strokeStyle = this.c;
ctx.strokeRect(this.x, this.y, this.width, this.height);
}
createArray() {
centerPoints.push({'x': this.center.x, 'y': this.z, 'z': this.center.y})
}
}

function createGrid() {
for (let y = 0; y < canvas.height; y += cellSize) {
for (let x = 0; x < canvas.width; x += cellSize) {
grid.push(new Cell(x, y));
}
}
}
createGrid();

function drawGrid() {
for (let i = 0; i < grid.length; i++) {
grid[i].draw();
grid[i].createArray();
}
}
drawGrid();

console.log(centerPoints)
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
<canvas id="canvas"></canvas>

Finding the closest grid coordinate to the mouse position with javascript/jQuery

I was initially writing an answer similar to bobince's, but he got there before me. I like that way of doing it, but his version has got some floors (though it's still a very good answer).

I presume that what you want is a HTML-less grid (that is, without markup like a table), which bobince supplies a solution for. In that case, the code may be optimised significantly for cross browser compatibility, readability, errors and speed.

So, I suggest the code should be more like this:

#canvas { position: relative; width: 100px; height: 100px; border: solid red 1px; }
#nearest { position: absolute; width: 10px; height: 10px; background: yellow; }

<div id="canvas"><div id="nearest"></div></div>

var
canvasOffset = $("div#canvas").offset(),
// Assuming that the space between the points is 10 pixels. Correct this if necessary.
cellSpacing = 10;

$("div#canvas").mousemove(function(event) {
event = event || window.event;
$("div#nearest").css({
top: Math.round((mouseCoordinate(event, "X") - canvasOffset.left) / cellSpacing) * cellSpacing + "px",
left: Math.round((mouseCoordinate(event, "Y") - canvasOffset.top) / cellSpacing) * cellSpacing + "px"
});
});

// Returns the one half of the current mouse coordinates relative to the browser window.
// Assumes the axis parameter to be uppercase: Either "X" or "Y".
function mouseCoordinate(event, axis) {
var property = (axis == "X") ? "scrollLeft" : "scrollTop";
if (event.pageX) {
return event["page"+axis];
} else {
return event["client"+axis] + (document.documentElement[property] ? document.documentElement[property] : document.body[property]);;
}
};

The mouseCoordinate() function is a boiled down version of these two functions:

function mouseAxisX(event) {
if (event.pageX) {
return event.pageX;
} else if (event.clientX) {
return event.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
}
};

function mouseAxisY(event) {
if (event.pageY) {
return event.pageY;
} else if (event.clientY) {
return event.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
}
};

I really like the idea of your project, perhaps I'll make something similar myself :D

How can I get grid row/col position given an item index

  1. Find how many elements fit in one row by taking the floor of (row width)/(element width).
  2. Divide the index number given by the elements per row (which you just figured out). That will give you the row position.
  3. Next find the column position by taking the remainder portion from step 1 (you can use modulus). Multiply the remainder by the number of elements per row. That will be which column it is in.

example: 3 elements per row, 4th element:
floor(4/3) = 1 (row 1)
remainder = (4%3)=1 (column position)

Be careful of what index you are starting with (whether it's 0 or 1). This example starts at 1. If you want to start at 0 shift it over by subtracting 1 (the index number).

How to find coordinates with cell number in a square grid

It is a classic problem in programming, converting 2D coordinates to 1D, it is usually done from 2D to 1D where indices start from 0 to length-1

First you have to figure out if you are in row-major or column-major:
https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Row_and_column_major_order.svg/170px-Row_and_column_major_order.svg.png

Most common case is row major. In this case imagine you have a 2D array with coordinates (x,y) in [0, width-1][0, height-1] and you want to convert to indices i in [0, width*height-1].

In row major, 2D->1D:

i = y * width + c

In row major, 1D->2D:

y = i / width  (euclidian division)
x = i % width (modulo operation which compute the remainder of euclidian division)

Get location of div on grid

in order to update the data object it would make it a little simpler if you change units to an object instead of array using the id as key for each element

"players" : {
"1" : {
"id" : 1,
"name": "ilya",
"units" : {
1: {
"id" : 1,
"row" : 1,
"square" : 2
},
2:{
"id" : 2,
"row" : 2,
"square" : 1
}
}

You can use index() method to get row and cell indexes. Using data- attributes for each element will help a lot.

When you read the data you can find the cell using eq() based on the values of row and squre in your data.

var $cell = $('tr').eq( row ).find('td').eq( square);
$('<div data-player="'+player.id+'" data-unit_id="'+unit+'"/>', {
class: 'draggable player' + player + ' unit unit' + unit,
}).appendTo($cell);

When you drop the unit in a new square:

/* pseudo code, not sure what your drop/append code looks like*/

var $cell= /* your logic to define the cell being placed in*/
var square= $cell.index();
var row= $cell.parent().index();
/* read player and unit from "data-" attributes of DIV*/
var unit= $(this).data('unit_id'), player= $(this).data('player');

Now with revised data structure it is very easy to update the main object players:

players[player].units[unit].row=row;
players[player].units[unit].square=square;

Simple Cell/Row Index demo: http://jsfiddle.net/buh4h/

API References:

http://api.jquery.com/index/

http://api.jquery.com/eq/



Related Topics



Leave a reply



Submit