Положение курсора в CSS положение сетки - PullRequest
1 голос
/ 20 января 2020

У меня есть сетка CSS, и я хочу получить положение ячейки ниже моего курсора. Представьте себе следующий пример:

enter image description here

Если мой курсор находится там, где находится звезда на изображении, я ищу функцию javascript, которая возвращает {grid-row-start: 2, grid-row-end: 3, grid-column-start: 5, grid-column-end: 6}.

Кто-нибудь из вас знает о встроенной функции для этого? Или я должен рассчитать значения сам? Спасибо:)

Код моего примера выглядит следующим образом:

<html>
    <head>
        <style>
            .container {
                display: grid;
                grid-gap: 10px;
                background-color: blue;
                grid-template-columns: repeat(6, 1fr);
                height: 400px;
            }
            .container div {
                background-color: green;
            }
            .grid-stack-item {
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="2" data-gs-height="1">
                <div class="grid-stack-item-content">1</div>
            </div>
            <div class="grid-stack-item" data-gs-x="2" data-gs-y="0" data-gs-width="2" data-gs-height="2">
                <div class="grid-stack-item-content">2</div>
            </div>
            <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="1" data-gs-height="1">
                <div class="grid-stack-item-content" style="overflow: hidden">3</div>
            </div>
            <div class="grid-stack-item" data-gs-x="5" data-gs-y="0" data-gs-width="1" data-gs-height="1">
                <div class="grid-stack-item-content"> 4</div>
            </div>
            <div class="grid-stack-item" data-gs-x="0" data-gs-y="1" data-gs-width="1" data-gs-height="1">
                <div class="grid-stack-item-content">5</div>
            </div>
            <div class="grid-stack-item" data-gs-x="1" data-gs-y="1" data-gs-width="1" data-gs-height="2">
                <div class="grid-stack-item-content">6</div>
            </div>

            <div class="grid-stack-item" data-gs-x="0" data-gs-y="2" data-gs-width="1" data-gs-height="1">
                <div class="grid-stack-item-content">8</div>
            </div>
            <div class="grid-stack-item" data-gs-x="2" data-gs-y="2" data-gs-width="2" data-gs-height="1">
                <div class="grid-stack-item-content">9</div>
            </div>
            <div class="grid-stack-item" data-gs-x="4" data-gs-y="2" data-gs-width="1" data-gs-height="1">
                <div class="grid-stack-item-content">10</div>
            </div>
            <div class="grid-stack-item" data-gs-x="5" data-gs-y="2" data-gs-width="1" data-gs-height="1">
                <div class="grid-stack-item-content">11</div>
            </div>
        </div>
    <script>
        for(let elm of document.getElementsByClassName('grid-stack-item')){
            elm.style['grid-column-start'] = parseInt(elm.getAttribute('data-gs-x')) + 1;
            elm.style['grid-column-end'] = parseInt(elm.getAttribute('data-gs-x')) + parseInt(elm.getAttribute('data-gs-width')) + 1;
            elm.style['grid-row-start'] = parseInt(elm.getAttribute('data-gs-y')) +1 ;
            elm.style['grid-row-end'] = parseInt(elm.getAttribute('data-gs-y')) + parseInt(elm.getAttribute('data-gs-height')) +1;
        }
    </script>
    </body>

</html>

Ответы [ 2 ]

1 голос
/ 20 января 2020

Идея в том, чтобы добавить дополнительный слой сетки за пределы контейнера. давайте назовем это «псевдоконтейнером». Этот псевдоконтейнер будет абсолютно позиционирован. Он будет содержать элементы в столбцах с шириной 16,6% и высотой, соответствующей сетке. Теперь мы можем связать указатель мыши с псевдоэлементами.

На основе ответа @Ian я сделал скрипку:

сначала создайте несколько псевдоэлементов:

var cont = $(".pseudoContainer");
for (var i = 0; i < 18; i++) {
var newDiv = document.createElement("div");
newDiv.setAttribute('class', 'pseudoitem');
  newDiv.innerHTML = '<div class="pseudoitem-inner"></div>';
  cont.append(newDiv);
}

затем добавьте слушателя:

Array.from(document.getElementsByClassName("pseudoitem-inner")).forEach(element => {
  element.addEventListener("mouseenter", () => {
    const style = window.getComputedStyle(element);
    currentCellPosition = {
      "grid-row-start": style.gridRowStart,
      "grid-row-end": style.gridRowEnd,
      "grid-column-start": style.gridColumnStart,
      "grid-column-end": style.gridColumnEnd
    }
    console.log(currentCellPosition);
  })
})

с некоторыми стилями, которые вы видите:

.pseudoContainer{
  position:absolute;
  top:0;
  left:0;
  width: 100%;
  display: block;
  padding: 3px;
   z-index:1;
}
.pseudoitem{
      width: calc(16.6% - 10px);
    height: 126px;
    float: left;
    padding: 5px 5px 5px;
    z-index:2;
}
.pseudoitem-inner{
  background-color: red;
    height: 100%;
    width: 100%;
}
.container{
  z-index:1;
}
.grid-stack-item{
  z-index:3;
}

теперь вам нужно только усовершенствовать процесс создания псевдоэлементов, чтобы они содержали информацию сетки.

вот скрипка

РЕДАКТИРОВАТЬ: Теперь вы получите необходимую информацию о перекладывании. Здесь также можно добавить дополнительный слой сетки за пределы контейнера и установить абсолютную позицию. К сожалению, это будет работать только для этой сетки, и это действительно не моя лучшая работа. В принципе, это то же самое, что и решение одно, но теперь здесь также используется стиль сетки.

var cont = $(".pseudoContainer");
var y,x;
for (var i = 0; i < 18; i++) {
if(i <= 5) y = 0, x = i;
if(i > 5 && i <= 11) y = 1, x = i - 6;
if(i > 11 && i <= 18) y = 2, x = i - 12;
  var newDiv = document.createElement("div");
  newDiv.setAttribute('class', 'pseudoitem');
  newDiv.setAttribute('data-gs-width', '1');
  newDiv.setAttribute('data-gs-height', '1');
  newDiv.setAttribute('data-gs-x', x);
  newDiv.setAttribute('data-gs-y', y);
  newDiv.innerHTML = '<div class="pseudoitem-inner"></div>';
  cont.append(newDiv);
}

for(let elm of document.getElementsByClassName('pseudoitem')){
            elm.style['grid-column-start'] = parseInt(elm.getAttribute('data-gs-x')) + 1;
            elm.style['grid-column-end'] = parseInt(elm.getAttribute('data-gs-x')) + parseInt(elm.getAttribute('data-gs-width')) + 1;
            elm.style['grid-row-start'] = parseInt(elm.getAttribute('data-gs-y')) +1 ;
            elm.style['grid-row-end'] = parseInt(elm.getAttribute('data-gs-y')) + parseInt(elm.getAttribute('data-gs-height')) +1;
        }


let currentCellPosition = {
  "grid-row-start": null,
  "grid-row-end": null,
  "grid-column-start": null,
  "grid-column-end": null
}

Array.from(document.getElementsByClassName("pseudoitem")).forEach(element => {
  element.addEventListener("mouseenter", () => {
    const style = window.getComputedStyle(element);
    currentCellPosition = {
      "grid-row-start": style.gridRowStart,
      "grid-row-end": style.gridRowEnd,
      "grid-column-start": style.gridColumnStart,
      "grid-column-end": style.gridColumnEnd
    }
    console.log(currentCellPosition);
  })
})

и стиль:

.pseudoContainer{
  position:absolute;
  top:10px;
  left:10px;
  width: 100%;
      height: 400px;
  display: grid;
   z-index:1;
   grid-template-columns: repeat(6, 1fr);
   grid-gap: 0px;
}
.pseudoitem{

    z-index:2;
}
.pseudoitem-inner{

    height: 100%;
    width: 100%;
}
.container{
  z-index:1;
}
.grid-stack-item{
  z-index:3;
}

EDIT2: I переписали расчет. теперь вы можете определить параметр «repeat» и «row», и будет автоматически создана сетка layer2.

обновлена ​​скрипка, и вот изменение кода:

var cont = $(".pseudoContainer");
var y,x;
var repeat = 6;
var rows = 3;
for (var i = 0; i < rows*repeat; i++) {

  if(i%repeat === 0) {
    y = i/repeat;
  }
  x = i- y * repeat;

  var newDiv = document.createElement("div");
  newDiv.setAttribute('class', 'pseudoitem');
  newDiv.setAttribute('data-gs-width', '1');
  newDiv.setAttribute('data-gs-height', '1');
  newDiv.setAttribute('data-gs-x', x);
  newDiv.setAttribute('data-gs-y', y);
  newDiv.innerHTML = '<div class="pseudoitem-inner"></div>';
  cont.append(newDiv);
}

for(let elm of document.getElementsByClassName('pseudoitem')){
            elm.style['grid-column-start'] = parseInt(elm.getAttribute('data-gs-x')) + 1;
            elm.style['grid-column-end'] = parseInt(elm.getAttribute('data-gs-x')) + parseInt(elm.getAttribute('data-gs-width')) + 1;
            elm.style['grid-row-start'] = parseInt(elm.getAttribute('data-gs-y')) +1 ;
            elm.style['grid-row-end'] = parseInt(elm.getAttribute('data-gs-y')) + parseInt(elm.getAttribute('data-gs-height')) +1;
        }


let currentCellPosition = {
  "grid-row-start": null,
  "grid-row-end": null,
  "grid-column-start": null,
  "grid-column-end": null
}

Array.from(document.getElementsByClassName("pseudoitem")).forEach(element => {
  element.addEventListener("mouseenter", () => {
    const style = window.getComputedStyle(element);
    currentCellPosition = {
      "grid-row-start": style.gridRowStart,
      "grid-row-end": style.gridRowEnd,
      "grid-column-start": style.gridColumnStart,
      "grid-column-end": style.gridColumnEnd
    }
    console.log(currentCellPosition);
  })
})

example

1 голос
/ 20 января 2020

Что вы хотите сделать, это выяснить, над каким элементом находится мышь, и затем получить window.getComputedStyle(element).gridColumnStart (и другие) из этого элемента.

Самый простой способ сделать это - просто добавить mouseenter событие для каждого из grid-stack-item элементов.

Вот пример:

let currentCellPosition = {
  "grid-row-start": null,
  "grid-row-end": null,
  "grid-column-start": null,
  "grid-column-end": null
}

Array.from(document.getElementsByClassName("grid-stack-item")).forEach(element => {
  element.addEventListener("mouseenter", () => {
    const style = window.getComputedStyle(element);
    currentCellPosition = {
      "grid-row-start": style.gridRowStart,
      "grid-row-end": style.gridRowEnd,
      "grid-column-start": style.gridColumnStart,
      "grid-column-end": style.gridColumnEnd
    }
  })
})

В этом примере currentCellPosition всегда будет иметь самую последнюю позицию в ячейке.

document.addEventListener("DOMContentLoaded", () => {
  const output = document.getElementById("output");

  Array.from(document.getElementsByClassName("cell")).forEach(element => {
    element.addEventListener("mouseenter", () => {
    const style = window.getComputedStyle(element)
      output.innerHTML = `
      row start: ${style.gridRowStart}
      row end: ${style.gridRowEnd}
      column start: ${style.gridColumnStart}
      column end: ${style.gridColumnEnd}
      `;
    })
  })
});
.container {
  border: 2px solid green;
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: auto auto;
  height: 200px;
  width: 100%;
}

.a {
  grid-row-start: 1;
  grid-row-end: 2;
  grid-column-start: 1;
  grid-column-end: 2;
  background-color: lightblue;
}
.b {
  grid-row-start: 2;
  grid-row-end: 3;
  grid-column-start: 1;
  grid-column-end: 3;
  background-color: orange;
}
.c {
  grid-row-start: 1;
  grid-row-end: 2;
  grid-column-start: 2;
  grid-column-end: 3;
  background-color: lightgreen;
}
<div class="container">
  <div class="a cell"></div>
  <div class="b cell"></div>
  <div class="c cell"></div>
</div>

<p id="output">

</p>
...