CSS网格布局 - 如何使用javascript计算鼠标所在的网格单元格?

时间:2016-12-17 13:15:24

标签: javascript css css3 css-grid

“css网格布局”= https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout

有没有人知道用javascript方法计算鼠标当前所在的列/行?

我猜这样的事情是获得鼠标所在单元格的开始,但是这只适用于相同尺寸的网格。

MouseGridColumn = round(mouseX / ( gridContainerWidth  / gridTotalColumnsNumber ) )
MouseGridRow    = round(mouseY / ( gridContainerHeight / gridTotalRowsNumber    ) )

有没有办法用不相等的细胞做到这一点?

更新1 - 添加codepen

这是一个codepen,它显示了3种不同的百分比列宽(grid-template-columns: 25% 50% 25%;),2行,一个没有元素的网格单元格和一个跨越多行的元素:http://codepen.io/anon/pen/NbeOXp < / p>

更新2 - 尝试计算鼠标所在的网格单元格。

在这里,我为网格中的每个单元格添加了隐藏元素,以检测鼠标所在的单元格。但是它只返回当前元素所在的“auto”。它还非常笨重,需要添加额外的隐藏元素网格IMO。

http://codepen.io/anon/pen/gLZBZw提示:使用鼠标悬停在网格上。

4 个答案:

答案 0 :(得分:3)

将事件侦听器添加到网格列的父级。它被称为事件授权。您可以在悬停事件中使用event.target并在内部循环比较ev.target.parent element==document.querySelect("#parentElement")[index] 如果你愿意,可以发布所有你的代码html代码来写它。

答案 1 :(得分:2)

我认为你正在寻找不同大小的网格的解决方案,当网格的概念是它们总是相同的大小(totalWidth / gridNumber)。只是元素可以溢出1,2,5或更多的网格。我做了一个小对象来检测网格数的变化,如果我误解了一些内容,请在评论中解释。

http://codepen.io/devrafalko/pen/bBOQbo?editors=1011

flex

答案 2 :(得分:0)

这里有两项任务:

  1. 检测元素。
  2. 获取元素的列/行。
  3. 检测元素

    如果为每个网格项添加所需的事件处理程序,则可以避免检测元素。

    但是如果你想添加鼠标悬停(或其他事件处理程序),你可以在每个网格项中添加循环并使用element.getBoundingClientRect()方法。演示(我将添加处理程序以便点击以避免污染控制台):

    &#13;
    &#13;
    var grid = document.querySelector(".grid");
    
    grid.addEventListener("click", function(event) {
      var gridItems = this.children;
      for (var i = 0; i < gridItems.length; i++) {
        var gridItem = gridItems[i];
        var rect = gridItem.getBoundingClientRect();
        var elementDetected = event.clientX >= rect.left
        	&& event.clientX <= rect.right
          && event.clientY >= rect.top
          && event.clientY <= rect.bottom;
        if (elementDetected) {
          console.log(gridItem);
          return;
        }
      }
      
      console.log("no element detected!");
    });
    &#13;
    .grid {
      display: grid;
      grid-template-columns: repeat(3, 100px);
      grid-template-rows: repeat(3, 100px);
      grid-gap: 10px;
    }
    
    /* styles just for demo */
    .grid__item {
      background-color: tomato;
      color: white;
      
      /* styles for centering text */
      display: flex;
      align-items: center;
      justify-content: center;
    }
    &#13;
    <div class="grid">
      <div class="grid__item">One</div>
      <div class="grid__item">Two</div>
      <div class="grid__item">Three</div>
      <div class="grid__item">Four</div>
      <div class="grid__item">Five</div>
      <div class="grid__item">Six</div>
      <div class="grid__item">Seven</div>
      <div class="grid__item">Eight</div>
      <div class="grid__item">Nine</div>
    </div>
    &#13;
    &#13;
    &#13;

    由于is(":hover")方法,使用jQuery会使这项任务变得更加简单。

    &#13;
    &#13;
    $(".grid").click(function(event) {
      var hoveredGridItems = $(this).children()
        .filter(function() { return $(this).is(":hover"); });
      
      if (hoveredGridItems.length > 0)
        console.log(hoveredGridItems[0]);
      else
        console.log("no element detected!");
    });
    &#13;
    .grid {
      display: grid;
      grid-template-columns: repeat(3, 100px);
      grid-template-rows: repeat(3, 100px);
      grid-gap: 10px;
    }
    
    /* styles just for demo */
    .grid__item {
      background-color: tomato;
      color: white;
      
      /* styles for centering text */
      display: flex;
      align-items: center;
      justify-content: center;
    }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="grid">
      <div class="grid__item">One</div>
      <div class="grid__item">Two</div>
      <div class="grid__item">Three</div>
      <div class="grid__item">Four</div>
      <div class="grid__item">Five</div>
      <div class="grid__item">Six</div>
      <div class="grid__item">Seven</div>
      <div class="grid__item">Eight</div>
      <div class="grid__item">Nine</div>
    </div>
    &#13;
    &#13;
    &#13;

    获取元素的列/行

    我只相信CSS,所以只有当我们明确设置grid-columngrid-row属性时,才能按预期工作。因此,您可以使用适用于所有情况的代码行:

    // pure JS
    var styles = window.getComputedStyle(gritItem);
    var gridColumn = styles["grid-column-start"];
    var gridRow = styles["grid-row-start"];
    
    // jquery
    var gridColumn = $gridItem.css("grid-column");
    var gridRow = $griditem.css("grid-row");
    

    如果gridColumn和/或gridRow的值不是auto / auto,那么您肯定知道行和列。

    但是,由于可能的列跨度/行跨度值,可能margins的网格项align-selfjustify-self,自动放置时检测行和列非常不可靠(例如, element只能占用网格区域的一部分)等。

答案 3 :(得分:0)

将带有自定义标签或类的空元素添加到网格的顶部和左侧边缘,使用“拉伸”对其进行样式设置,然后将宽度/高度相加以获取网格线的坐标。