2016-11-29 4 views
2

Используя букмарклет, я хотел бы связать элемент img с обработчиком для событий mouseenter и mouseleave с помощью jquery .hover(), но в некоторых случаях события мыши никогда не будут вызвано тем, что элемент img каким-то образом скрыт от мыши, несмотря на то, что изображение на самом деле видимо: простой пример - это когда перекрывается прозрачный элемент. Если вы играете с помощью инструмента, такого как инспектор Firebug, вы найдете много таких примеров.Программно определить, может ли элемент быть зависающим или нет

Как я могу понять такое поведение? В идеале я хотел бы построить функцию, которая вернет true или false в зависимости от того, является ли элемент зависящим или нет.

Спасибо всем

+0

Я не думаю, что это возможно, потому что каждый элемент может зависнуть. Элементы не знают об их отношениях друг с другом, поэтому вы не можете их просить. –

+0

@AniketSahrawat да, но это не ответит на вопрос OP о прозрачных элементах. –

+1

@charlieg когда-нибудь вы можете что-то сделать, используя document.elementFromPoint (x, y), но мне хотелось бы что-то более полное – JaneCC

ответ

5

Проблемы:

Реальная проблема заключается в том, что существует так много способов, которые могут быть покрыты элемент. Например, элемент, покрытый четырьмя другими элементами, и просто пространство открыто посередине? Пример того, что я имею в виду:

enter image description here

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

Из-за этих проблем может возникнуть очень «дорого», чтобы определить, имеет ли элемент какую-либо нависшую область.

Решение:

Я придумал решение с использованием boundingClientRect, document.elementFromPoint и скроллинг документа. Он пытается быстро определить, проверив 4 угла соответствующего элемента, а затем, если они вернутся назад, начните проверять весь элемент с помощью определенной «точности».

UPDATE:

Я добавил в пути, чтобы проверить элементы, которые даже не в окне просмотра. Это работает, пытаясь прокрутить элемент, запустить проверку, а затем прокрутить назад до предыдущей позиции до начала проверки. Это происходит так быстро, что никаких видимых скачков не происходит.

function getOffset(el) { 
    el = el.getBoundingClientRect(); 
    return { 
     left: el.left + window.scrollX, 
     top: el.top + window.scrollY 
    } 
} 

function isElementHoverable(element) { 
    var pageX = window.scrollX; 
    var pageY = window.scrollY; 
    var elementXY = getOffset(element); 
    var accuracy = 1; 
    var canBeHovered = false; 

    window.scrollTo(elementXY.left, elementXY.top); 

    var box = element.getBoundingClientRect(); 

    // try the 4 corners first 
    if (
     element == document.elementFromPoint(box.left, box.top) || 
     element == document.elementFromPoint(box.left, box.bottom - 1) || 
     element == document.elementFromPoint(box.right - 1, box.top) || 
     element == document.elementFromPoint(box.right - 1, box.bottom - 1) 
    ) { 
     canBeHovered = true; 
    } 

    loop1: 
     for (let i = box.left; i < box.right; i += accuracy) { 
      for (let j = box.top; j < box.bottom; j += accuracy) { 
       if (element == document.elementFromPoint(i, j)) { 
        canBeHovered = true; 
        break loop1; 
       } 
      } 
     } 

    window.scrollTo(pageX, pageY); // Scroll back to the original position 
    return canBeHovered; 
} 

I worked up an actual example on JSFiddle (пример был обновлен, чтобы отразить элементы прокручивать страницу вниз), в комплекте с парой испытаний. Вам нужно будет открыть консоль браузера, чтобы просмотреть результаты тестов. Вероятно, вы также захотите проверить это в Chrome или Firefox, так как я не тестировал это за пределами этого.


Несколько вещей, чтобы помнить:

Если проверка 4 угла выходит из строя, то он становится дорогим, чтобы проверить остальную часть элемента. Чем меньше число «точность», тем дороже оно получается. Это число определяет, как часто запускать проверку. Так что если точность 1, то она будет проверять каждый 1px. Если число равно 10, то он проверяет каждые 10 пикселей на оси X и Y.

Следует отметить, что практически нет способов узнать варианты элементов на странице. Вы отмечаете в комментарии, что некоторые элементы могут исчезнуть, которые были «блокированы» во время проверки, но не во время взаимодействия пользователя.Невозможно узнать об этой функциональности, кроме AI. Однако эта функция предназначена для вашего выбора, а не только для загрузки страницы.

+0

Это интересно, потому что это именно то решение, которое я пробовал, прежде чем задавать этот вопрос (см. Https://stackoverflow.com/a/ 40877241/7221380), это неплохо, но есть и недостатки: – JaneCC

+0

1) это будет работать только тогда, когда элемент находится внутри области просмотра, поэтому, если вы не прокрутите адекватно окно через javascript для каждого элемента, это не будет работать для всего элемента. 2) Я видел некоторую ситуацию, когда элемент1 покрыт элементом2, и когда вы наводите элемент element2, тогда элемент 1 приходит сверху, а затем элемент1 является зависящим. Я знаю, что это своего рода экстремальная ситуация, но, возможно, другие, о которых я не помню (создание списка такой ситуации приветствуется). – JaneCC

+0

Теперь, если в ближайшие дни не будет лучшего решения, я приму свой ответ, который может быть близок к лучшему, что можно достичь в этом отношении. Спасибо за попытку. – JaneCC

Смежные вопросы