Добавление реализации границы для виджета при наведении, как в webflow

#dom #webflow

#javascript #HTML #dom

Вопрос:

В webflow, когда мы наводим курсор на элемент, он показывает синюю рамку.(Смотрите Видео) Мне интересно узнать, как это реализовано. Я провел свое исследование и мог бы сделать базовое предположение о его реализации.

1 Прослушайте событие наведения курсора мыши на тело 2, затем при обновлении курсора мыши используйте document.getelementfrompoint(), чтобы получить узел элемента в точке, в которой теперь используется абсолютно позиционированный div, добавьте границу в прямой узел наведенного курсора.

Вопрос, правильно ли мое предположение? Существует ли пороговое значение, которое нам нужно проверить, чтобы избежать вызова обработчика перемещения мыши?

введите описание изображения здесь

Комментарии:

1. Похоже, вы могли бы сделать это в CSS с помощью сочетания :hover , ::after , и outline . Javascript не требуется.

Ответ №1:

Вот оно… Я не думаю, что есть какие-либо проблемы с запуском событий mousemove. Я вообще не использовал порог (без отмены).

РЕДАКТИРОВАТЬ — Ответ на вопрос OP в комментариях:

Почему вы не использовали e.target вместо document.elementFromPoint(e.pageX, e.pageY) ?

Хороший вопрос! Сначала я попробовал этот .elementFromPoint() метод, потому что я не знал об этом до вашего вопроса. И это сработало хорошо. Я думаю, это называется «удача новичка»! лолл! — Теперь я только что попробовал e.target и увидел скачкообразный эффект, который мотивировал ваш вопрос о пороге.

Причина скачкообразного эффекта проста. В mousemove сгенерированном объекте события содержится целевой элемент, верно? И это элемент под указателем. Однажды это нужный элемент… И, во-вторых, это добавленный «пограничный div» из нашего скрипта. И это циклически повторяется без остановки.

Теперь, используя document.elementFromPoint(e.pageX, e.pageY) , это ВСЕГДА нужный элемент, потому что двумя строками выше в скрипте мы удаляем предыдущий «пограничный div», а ЗАТЕМ запрашиваем элемент под указателем.

 function showElement(e) {

  // If there is already an appended div, remove it
  let prev = document.querySelector(".border")
  if(prev){
    prev.remove()
  }

  // Get the element. If there's none, stop here to avoid errors
  let elem = document.elementFromPoint(e.pageX, e.pageY)
  if(!elem){return}
  let elemTagname = elem.tagName.toLowerCase()
  let elemRect = elem.getBoundingClientRect()

  // Create a div to show the elem borders
  let border = document.createElement("div")
  border.classList.add("border")
  border.style.top = elemRect.top   "px"
  border.style.left = elemRect.left   "px"
  border.style.width = elemRect.width   "px"
  border.style.height = elemRect.height   "px"
  
  // Create a span to show the tag name
  let tag = document.createElement("span")
  tag.classList.add("tag")
  tag.innerText = elemTagname
  
  // Append!
  border.append(tag)
  document.documentElement.append(border)
}

// Mousemove handler
document.documentElement.addEventListener("mousemove", showElement) 
 div{
  height: 300px;
}

.border{
  border: 1px solid blue;
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
}

.tag{
  background: lightgrey;
  color: blue;
  font-family: arial;
  margin-left: 0.3em;
  padding: 0 0.3em;
} 
 <div>
  <h1>Header</h1>
  <p>Paragraph</p>
  <ul>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
  </ul>
</div> 

Комментарии:

1. Спасибо за ваши усилия. Мне любопытно узнать, почему вы не использовали «e.target» вместо «document.elementFromPoint (например,pageX, например, pageY)».

2. Я отредактировал с длинным ответом 😉