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
- Find how many elements fit in one row by taking the floor of (row width)/(element width).
- Divide the index number given by the elements per row (which you just figured out). That will give you the row position.
- 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:
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
Using JavaScript to Compare Two Input Numbers in HTML
Attribute Onclick="Function()" Not Functioning as Intended
How to Save Data from a Form with HTML5 Local Storage
Changing Data Content on an Object Tag in HTML
How Does the Location of a Script Tag in a Page Affect a JavaScript Function That Is Defined in It
How to Dynamically Adjust CSS Stylesheet Based on Browser Width
Detect Failure to Load Contents of an Iframe
How to Detect When a New Element Has Been Added to the Document in Jquery
How to Clear/Remove JavaScript Event Handler
Issue with Comparing Two Numbers in JavaScript
Why Does Getelementbyid Not Work on Elements Inside the Document Element
Specify Parent Divs Opacity But Make It Not Affect Children HTML Elements
Changing the Url Without Reloading the Page
CSS Position Absolute Making the Textbox Go Down
Jquery Event Not Triggering for Dom Elements Created After Page Load
Resize Iframe Height According to Content Height