2016-11-22 66 views
0

我正在使用document.elementFromPoint API来获取某个元素。但我不想拥有所有元素 - 有些不合格,如inline元素。因此,我将不合格的元素暂时隐藏起来,以便抓住它下面的元素。临时使元素不可见

这是一段代码摘录。

import { elementQualified, elementFromPoint } from './utils'; 

function makeInvisible(element) { 
    let oldVisibility = element.style.visibility; 

    /* this is supposed to make the element invisible immediately, without 
    * any delay. When a `transition` property is set which includes the 
    * `visibility` property, this is sometimes unfortunately not the case. */ 
    element.style.visibility = "hidden"; 

    /* this is the undo function being called at the end. */ 
    return() => { 
    element.style.visibility = oldVisibility; 
    }; 
} 

export default function(x, y) { 
    var undo = [], element, last; 

    /* in a loop, we grab the top-most element that is at a certain coordinate 
    * inside the viewport. The `last` variable is preventing an infinite loop 
    * in cases, where `makeInvisible()` does not work. */ 
    while (((element = elementFromPoint(x, y)) !== null) && (last !== element)) { 
    /* 
    * In order to be qualified, this element including its ancestors must 
    * all be qualified. For instance, if this is a block element but the 
    * parent for some reason is an inline element, this is not desired. */ 
    if (withAncestors(element).every(elementQualified)) { 
     break; 
    } 

    /* if the element is not qualified, we make it invisible and add it to the 
    * start of the `undo` array which is being batch-called after this loop. */ 
    undo.unshift(makeInvisible(element)); 

    /* and the loop protection */ 
    last = element; 
    } 

    /* undo all changes */ 
    undo.forEach((fn) => fn()); 

    /* check if we broke the loop or we have selected the topmost element 
    * in which case we discard the result. */ 
    if ((last === element) || (element === document.documentElement)) { 
    return null; 
    } 

    return element; 
} 

如果应该成为无形的元素有一个transition属性集,其中包括了visibility财产,也不会立即成为无形。以transition: all 0.3s ease-in-out为例。将element.style.visibility设置为hidden后,将需要0.3s,之后该元素实际上不可见,并且document.elementFromPoint将选择其下的元素。因此,循环正在中断,因为document.elementFromPoint正在返回相同元素的两倍。

我并不打算临时设置display属性,因为它会导致布局更改,而我正在构建一个布局更改无效的工具。

+0

广东话你设置元素为不可见之前删除的过渡,并设置回一旦你的元素,然后有一个超时(1ms的应该是足够了)上完成? – Lain

+0

“_...显示属性...导致布局变化_”它不会,当你做所有的DOM处理同步,并设置一切回到给浏览器呈现页面的机会之前。因此,如果在脚本结束之前删除样式,那么脚本中的“display:none”不会显示在页面上。 – Teemu

+0

我曾尝试过'display:none'选项。它会导致一些布局更改和滚动问题。 – Vincent

回答

1

由于躺在建议,disable transitionsmakeInvisible一个重置过渡性质

+1

我发现有可能在没有超时的情况下重新启用转换。我只需将'visibility'设置为旧值,然后在设置'transition'属性之前导致布局回流。 – Vincent