2016-11-22 12 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; 
} 

見えなくなることになっている要素はvisibilityプロパティが含まtransitionプロパティセットを持っている場合、それはすぐに見えなくなることはありません。たとえばtransition: all 0.3s ease-in-outとします。 element.style.visibilityhiddenに設定した後は、0.3sになります。その後、実際には表示されず、document.elementFromPointはその下の要素を選択します。その結果、document.elementFromPointが同じ要素の2倍を返すため、ループが壊れています。

displayプロパティを一時的に設定するつもりはありません。レイアウトが変更され、レイアウト変更が機能しないツールを作成しているためです。遷移プロパティをリセットします

+0

カントあなたは目に見えないに要素を設定する前にトランジションを削除したら、それをバックに設定しますされていますか? – Lain

+0

"_... display property ...レイアウトの変更を引き起こします。" "すべてのDOMを同期的に処理していて、ブラウザにページをレンダリングする前にすべてを元に戻してしまうと、そうしません。したがって、スクリプトが終了する前にスタイリングを削除すると、スクリプトに 'display:none'を設定することはページに表示されません。 – Teemu

+0

前に 'display:none'オプションを試しました。それは私のためにレイアウトの変更やスクロールの問題を引き起こします。 – Vincent

答えて

1

示唆したレインとして、makeInvisibleの要素にdisable transitions、その後、タイムアウトを持っている(1ミリ秒は十分なものでなければならない)

+1

私は、トランジションを再度有効にするためのタイムアウトなしでこれを行うことが可能であることを発見しました。私は単純に 'visibility'を古い値に設定し、' transition'プロパティを設定する前にレイアウトのリフローを引き起こします。 – Vincent

関連する問題