如何使用JavaScript获取元素的网格坐标?

11

假设我有一个三列的CSS-Grid。是否可以使用JavaScript来获取自动放置元素的grid-rowgrid-column

例子:

console.log($('#test').css('grid-row'), $('#test').css('grid-column'));
// expected output: 2 3 
// actual output: two empty strings
.grid {
  display: grid;
  grid-template-columns: repeat( 3, 1fr);
}
<div class="grid">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div id="test"></div>
  <div></div>
  <div></div>
  <div></div>
</div>

这是一个JSFiddle示例: https://jsfiddle.net/w4u87d2f/7/

在这个例子中,我可以通过计算元素的数量并知道网格有三列来找出解决方法:

grid-column = $('#test').index() % 3 + 1;
grid-row = Math.ceil( $('#test').index() / 3 )

但这仅适用于非常简单的网格,并且意味着我必须考虑会更改列数的断点。

编辑:这不是检索HTML元素位置(X,Y)的重复,因为我不感兴趣像素坐标,而是在CSS-Grid内的行和列编号。


1
为什么不直接把它放到“id”中,让生活变得更简单呢? - James Gould
@JayGould,因为在我要解决的任务中,我没有一个“id”,行号将取决于断点。 - Seraphithan
@Rainb,我不确定你的意思,我在移动设备上应该如何处理? - Seraphithan
@Seraphithan 我想我可能有一个解决方案,我会将其发布为答案。您将如何确定类= grid 的 div 中元素的位置,当单击它时,它是否会添加类属性,或者工作流程是什么? - Ryan Wilson
这个回答解决了你的问题吗?如何使用JavaScript查找CSS网格布局元素位于哪一列 - clickbait
显示剩余5条评论
3个回答

10

上面的答案是一个很好的开始,使用了jQuery。这里提供了一个纯JavaScript的等价物,并且还实现了"offset",以防您指定了第一个子元素的网格列(例如在日历中指定月份的第一天)

function getGridElementsPosition(index) {
  const gridEl = document.getElementById("grid");

  // our indexes are zero-based but gridColumns are 1-based, so subtract 1
  let offset = Number(window.getComputedStyle(gridEl.children[0]).gridColumnStart) - 1; 

  // if we haven't specified the first child's grid column, then there is no offset
  if (isNaN(offset)) {
    offset = 0;
  }
  const colCount = window.getComputedStyle(gridEl).gridTemplateColumns.split(" ").length;

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

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

function getNodeIndex(elm) {
  var c = elm.parentNode.children,
    i = 0;
  for (; i < c.length; i++) if (c[i] == elm) return i;
}

function addClickEventsToGridItems() {
  let gridItems = document.getElementsByClassName("grid-item");
  for (let i = 0; i < gridItems.length; i++) {
    gridItems[i].onclick = (e) => {
      let position = getGridElementsPosition(getNodeIndex(e.target));
      console.log(`Node position is row ${position.row}, column ${position.column}`);
    };
  }
}

addClickEventsToGridItems();

这里有一个对应的笔,可以在带有指定偏移量的日历上展示它的功能。


2
感谢提供纯JS版本。之前不知道window.getComputedStyle(),现在真的是一个改变游戏规则的东西。 - Elpy
这里有很棒的想法。想知道如果在React中构建了列和行,我该如何实现这个想法。 - undefined

7
//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 } ;
}

如果这不是你要找的,请告诉我,我会将其删除。 - Ryan Wilson
这看起来很不错,谢谢。我认为我甚至可以调整它以适应IE 11网格。希望最终会有一种直接访问这些参数的方法,因为我认为如果一个元素跨越多行或多列,这将会破坏它,但幸运的是这对我的任务没有影响。 - Seraphithan
@seraphithan 如果一个元素可以跨越多个列或行,我需要看一个例子,也许可以修改它,很高兴能帮到你。 - Ryan Wilson

0

这里提供另一种解决方案,考虑列跨度

function getGridPosition(elem) {
    var gridContainer = elem.parent();
    var simpleEl = elem.get(0);
    var gridItems = gridContainer.children('div');
    const colCount = $(gridContainer).css('grid-template-columns').split(' ').length;

    var row = 0;
    var col = 0;

    gridItems.each(function(index,el) {

        var item = $(el);
        if(simpleEl==el) {
            //console.log("FOUND!")
            return false;
        }
        var gridCols  = item.css("grid-column");
        if(gridCols != undefined && gridCols.indexOf("span")>=0){
            var gridColumnParts = gridCols.split('/');
            var spanValue = parseInt(gridColumnParts[0].trim().split(' ')[1], 10);
            //console.log("spanValue: " + spanValue);
            col = col+spanValue;
        }else{
            col++;
        }
        if(col>=colCount){
            col=0;
            row++;
        }
    });

    return {
        row: row,
        col: col
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接