12

更新すべての要素の親に戻って順番にテストすることは避けたいのですが、これがthis answerのように、これまでに見つけた最良の解決策です。


イベント ハンドラー内で、ターゲット要素の位置がビューポート (固定) またはドキュメント (静的、相対、または絶対) に対して相対的であるかどうかを検出したいと考えています。

「position:fixed」があるため、またはその親の 1 つが「position:fixed」であるため、要素の位置が固定されている可能性がある場合、要素の固定位置を検出する効率的な方法は何ですか?

例えば:

CSS

#one {position:relative; height:10px; width:10px}

#two-wrapper {position:fixed; bottom:0; height:10px; width:10px}
#two {height:10px; width:10px}

HTML

<div id="one" class="trigger-event">element one</div>

<div id="two-wrapper">
    <div id="two" class="trigger-event">element two</div>
</div>

JS

$(document).ready(function(){
    $('.trigger-event').on('mouseenter', function(event){
        var isFixed = .... ????

        if (isFixed) {
            $(event.target).css('background','red'); 
        } else {
            $(event.target).css('background','green'); 
        }
    });
});
4

6 に答える 6

14

これは、要素の親をたどって、それぞれの CSS 位置の値を順番にチェックすることに基づく解決策です。

これは最も効率的な方法ですか、それとも要素自体を調べるだけで効果的な配置を検出する方法はありますか?

http://jsfiddle.net/Q4mSJ/

CSS

.trigger-event {background:#ccc}

#one {position:relative; height:50px; width:50px}

#two-wrapper {position:fixed; bottom:0; height:50px; width:50px}
#two {height:50px; width:50px}

HTML

<div id="one" class="trigger-event">element one</div>

<div id="two-wrapper">
    <div id="two" class="trigger-event">element two</div>
</div>

JS

function elementOrParentIsFixed(element) {
    var $element = $(element);
    var $checkElements = $element.add($element.parents());
    var isFixed = false;
    $checkElements.each(function(){
        if ($(this).css("position") === "fixed") {
            isFixed = true;
            return false;
        }
    });
    return isFixed;
}

$(document).ready(function(){
    $('.trigger-event').on('mouseenter', function(event){
        var isFixed = elementOrParentIsFixed(event.target);

        if (isFixed) {
            $(event.target).css('background','red'); 
        } else {
            $(event.target).css('background','green'); 
        }
    });
});
于 2013-10-20T07:28:24.260 に答える
3

更新されました。以下を参照してください...

このための純粋な JavaScript ソリューションを検索しているときに、ここに立ち寄りました...しかし、誰かが私の jquery バージョンを気に入ってくれることを願っています。

わずかに異なる動作をする 2 つの関数を次に示しますが、パフォーマンスの違いは最小限です。私はそれを測定しませんでしたが、jsperf "each vs filter"でのこのテストによると、.each()バージョンはわずかに高速です。

それにもかかわらず、私はこの.filter()バージョンがとても短くてわかりやすいので気に入っています。

$.fn.isfixed = function(){
    var el = $(this);
    var all = el.add(el.parents());
    return all.filter(function(){
        return $(this).css("position") === "fixed";
    }).length > 0;
};

$.fn.isfixed = function(){
    var el = $(this);
    var all = el.add(el.parents());
    var ret = false;
    all.each(function(){
        if ($(this).css("position") === "fixed") {
            ret = true;
            return false;
        }
    });
    return ret;
};

使用方法は$('path > to > your > element').isfixed()返品trueまたはfalse

アップデート

そして、これが純粋なJavaScriptバージョンです。(固定/絶対/相対)を検出することel.style.positionは機能せず、理由はわかりませんが、機能することが判明しましたwindow.getComputedStyle(el)...

var isfixed = function(elm) {
    var el;
    if (typeof elm === 'object') el = elm[0] || elm;
    else if (typeof elm === 'string') el = document.querySelector(elm);
    while (typeof el === 'object' && el.nodeName.toLowerCase() !== 'body') {
        if (window.getComputedStyle(el).getPropertyValue('position').toLowerCase() === 'fixed') return true;
        el = el.parentElement;
    }
    return false;
};

次の 3 種類の要素パラメータを受け入れます:
JavaScript オブジェクトとして:
var obj = document.querySelector('div#myID > span');
または
var obj = document.getElementById('span#someID');

jquery オブジェクトとして:
var obj = $('div#myID > span');

またはセレクタのみとして:
var obj = 'div#myID > span';

使用法は単純isfixed(obj);で、ブール値trueまたはfalse

そして、これが最終的に混合ソリューションです(jqueryプラグインとしての純粋なjavascript)

$.fn.isfixed = function(){
    var el = this[0];
    while (typeof el === 'object' && el.nodeName.toLowerCase() !== 'body') {
        if (window.getComputedStyle(el).getPropertyValue('position').toLowerCase() === 'fixed') return true;
        el = el.parentElement;
    }
    return false;
};

使用法:$('div#myID > span').isfixed()上記の例のように。
気に入っていただけると幸いです。

于 2017-05-07T17:36:03.197 に答える