13

サムネイルにカーソルを合わせると、完全な画像をサムネイルに動的に追加するスクリプトがあります。また、完全な画像に CSS :hover スタイルを与えて、より大きな幅に拡大できるようにしました (通常、画像はサムネイルのサイズに制限されます)。これは、画像がすばやく読み込まれるか、キャッシュされている場合はうまく機能しますが、完全な画像の読み込みに時間がかかり、読み込み中にマウスを動かさない場合、通常はサムネイルの幅のままになります ( non-:hover スタイル) は、マウスをもう一度動かすまで続きます。試したすべてのブラウザーでこの動作が発生します。これがバグなのか、修正または回避する方法があるのか​​ 疑問に思っています。

.on('mouseenter')を使用して Javascript で同じことをしようとして、同じ問題に遭遇したことは注目に値するかもしれません。

問題の性質上、特に接続が高速な場合は、再現が難しい場合があります。デモ用にウィキペディアから大きな写真を選びましたが、それを機能させるには、特に大きな写真や遅いドメインの写真に変更する必要があるかもしれません。また、連続して再試行するためにキャッシュをクリアする必要がある場合があることに注意してください。

それでも再現できない場合は、 をfullimage.load呼び出す前に人為的な遅延を に追加できますanchor.show()

HTML:

<img id="image" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Cairo_International_Stadium.jpg/220px-Cairo_International_Stadium.jpg" />

CSS:

.kiyuras-image {
    position: absolute;
    top: 8px;
    left: 8px;
    max-width: 220px;
}

.kiyuras-image:hover {
    max-width: 400px;
}

JS:

$(function () {

    var fullimageurl = 'http://upload.wikimedia.org/wikipedia/commons/3/32/Cairo_International_Stadium.jpg';

    var fullimage = $('<img/>')
        .addClass('kiyuras-image')
        .load(function () {
            anchor.show();
        });

    var anchor = $('<a/>').hide().append(fullimage);

    $('body').prepend(anchor);

    $("#image").on('mouseenter', function () {
        fullimage.attr('src',fullimageurl);
        $(this).off('mouseenter');
    });

});

JSビン

JS Bin を更新し、1.5 秒の遅延を追加しました (うまくいけば、問題がより明確になります)

繰り返しますが、問題を再現するには、大きな画像のキャッシュをクリアし、元の画像にカーソルを合わせて大きな画像の読み込みを開始し、読み込み中はマウスを動かさないようにします。意図された動作は、大きな画像が最終的に読み込まれるときに :hover 疑似クラスを適切に取得することです。読み込みに 0.75 秒以上かかる場合に表示される問題は、マウスを少し揺らすまで :hover にならないことです。

編集: 私のユースケースの詳細については、@LucaFagioli の回答に関する私のコメントを参照してください。

編集、続編:私はすでにこれをやったと思っていましたが、Firefoxで問題を再現しようとしましたが、できませんでした. おそらくこれはChromeのバグですか?

4

9 に答える 9

7

ほとんどのブラウザーhoverは、カーソルが要素上で少なくとも 1 ピクセル移動した場合にのみ状態を更新します。カーソルがサムネイルに入ると、カーソルimghover適用され、mouseenterハンドラーが実行されます。フルサイズの画像が読み込まれるまでカーソルを静止させたままにすると、古いimg(サムネイル) はhover状態を保持し、新しいものはそれを取得しません。

これらのブラウザーで動作させるには、hover疑似クラスを CSS の共通の親要素に移動します。たとえば、両方の を で囲みimgspanます。

于 2012-11-06T20:41:58.067 に答える
2

セレクターが正しければ、CSS はすべての要素 (動的またはその他) に適用されます。これにはすべての疑似クラスが含まれ、DOM の属性が変更されると変更されます。

于 2012-10-29T11:25:22.033 に答える
1

[編集: 私の説明は興味深いかもしれませんが、上記の pozs のソリューションの方が優れているため、可能であればそれを使用することをお勧めします。]

hover疑似クラスの仕様は、いつアクティブ化する必要があるかに関して非常に緩和されています。

CSS は、どの要素が上記の状態になるか、またはどのように状態に入ったり出たりするかを定義していません。スクリプトは、要素がユーザー イベントに反応するかどうかにかかわらず変化する可能性があり、デバイスや UA が異なれば、要素を指し示す方法やアクティブ化する方法も異なる可能性があります。

特に、読み込み時にアンカー要素の可視性を更新すると、アクティブ化されません。

これはかなり簡単に回避できます。hoverスタイルをクラスにコピーし、カーソルが最終的にカバーする要素の上を移動するのをインターセプトし、それに基づいて、要素からクラスを追加または削除します。

デモ: JS Bin (遅れた例に基づく) .

Javascript:

$("#image")
  .on('mouseenter', function () {
    fullimage.attr('src',fullimageurl).toggleClass('mouseover', true);
    $(this).off('mouseenter');
  })
  .mouseleave(function() {
    fullimage.toggleClass('mouseover', false);
  });

CSS:

.kiyuras-image:hover, .kiyuras-image.mouseover {
    max-width: 400px;
}
于 2012-11-06T15:08:57.233 に答える
1

TL;DR:hover :カーソルの下に動的に追加された要素に適用することに依存することはできません。ただし、純粋な CSS と Javascript の両方で使用できる回避策があります。

私は Jordan Gray と posz の両方の回答に賛成しています。Jordan Gray は、CSS 仕様に関する問題にやや決定的な方法で対処し、(別の) 動作する修正を提供しました。posz は、さらにうまく機能し、どのホバー イベントでも Javascript を回避するソリューションを提供しました。ここでは基本的に同じソリューションを提供しますが、スパンの代わりに div を使用します。彼に授与することにしましたが、ジョーダンのインプットは不可欠だったと思います。このすべてについて自分でさらに詳しく説明する必要があると感じたので、私は自分の答えを追加して受け入れています。(編集: 変更しました。posz を受け入れました)

Jordan は CSS2 仕様を参照しました。代わりに CSS3 を参照します。私が知る限り、彼らはこの点で違いはありません。

問題の疑似クラスは :hover で、ユーザーが「ポインティング デバイスで指定した」要素を参照します。動作の正確な定義は、さまざまな種類のインタラクションとメディアを考慮して、意図的にあいまいなままになっています。これは、残念ながら、仕様が次のような質問に対応していないことを意味します。 " これは答えるのが難しい質問です。ほとんどの場合、ユーザーの意図に沿った回答はどれですか? ユーザーが操作しているページへの動的な変更は、通常、進行中のユーザー操作またはその準備の結果です。したがって、私はイエスと答えます。現在のほとんどのブラウザーは同意しているようです。通常、カーソルの下に要素を追加すると、:hover がすぐに適用されます。これはここで見ることができます:私が最初に投稿したjsbin。大きな画像の読み込みに遅延がある場合は、後で説明する理由により、ページを更新して機能させる必要がある場合があることに注意してください。

現在、ユーザーが :hover ルールを使用して要素の上にカーソルを固定した状態でブラウザー自体をアクティブにする同様のケースがあります。その場合は適用されますか?この場合のマウスの「ホバー」は、直接のユーザー操作の結果ではありません。でも、ポインティングデバイスが指定してるんですよね?その上、マウスの動きは確かに明確な相互作用をもたらします。これは答えるのが難しい質問であり、ブラウザーはさまざまな方法で回答します。Chrome と Firefox は、それらを有効にしているとき、マウスを動かすまで :hover 状態を変更しません (クリックして有効にしても!)。一方、Internet Explorer は、アクティブになるとすぐに :hover 状態を更新します。実際、マウスの下で最初に表示されているウィンドウである限り、アクティブでない場合でも更新されます。

ただし、最初のケースに戻りましょう。それが私の現在の問題が発生する場所だからです。私の場合、ユーザーは長時間 (1 秒以上) マウスを動かしておらず、カーソルのすぐ下に要素が追加されています。これは、ユーザーの操作があいまいで、疑似クラスを切り替えてはならない場合であると簡単に主張できます。個人的には、まだ適用されるべきだと思います。ただし、ほとんどのブラウザーは私に同意していないようです。初めて画像にカーソルを合わせてから、この jsbinでマウスを動かさない場合(問題を示すために質問に投稿したもので、最初のものと同様に、単純な :hover セレクターがあります)、 :hover クラスはそうではありません現在の Chrome、Opera、および IE に適用されます。(Safari も適用されませんが、興味深いことに、キーボードのキーを押し続けると適用されます。) ただし、Firefox では、:hover クラスすぐに適用されます。最初にテストしたのは Chrome と Firefox の 2 つだけだったので、これは Chrome のバグだと思いました。ただし、仕様はこの点について多かれ少なかれ完全に沈黙しています。ほとんどの実装はノーと言います。Firefox と私は賛成です。

仕様の関連セクションは次のとおりです。

:hover 疑似クラスは、ユーザーがポインティング デバイスで要素を指定している間に適用されますが、必ずしもアクティブ化するとは限りません。たとえば、ビジュアル ユーザー エージェントは、カーソル (マウス ポインター) が要素によって生成されたボックスの上に置かれたときに、この疑似クラスを適用できます。インタラクティブ メディアをサポートしないユーザー エージェントは、この疑似クラスをサポートする必要はありません。インタラクティブ メディアをサポートする一部の準拠ユーザー エージェントは、この疑似クラスをサポートできない場合があります (たとえば、ホバリングを検出しないペン デバイス)。

[...]

セレクターは、':active' または ':hover' である要素の親もその状態にあるかどうかを定義しません。

[...]

注: 子がポインティング デバイスによって指定されているために ':hover' 状態が要素に適用される場合、':hover' がポインティング デバイスの下にない要素に適用される可能性があります。

そう!回避策に進みます!このスレッドで何人かが熱心に指摘しているように、Javascript と jQuery は、'mouseover' と 'mouseenter' DOM イベントに依存して、これに対するソリューションも提供します。この質問をする前と後の両方で、私はこれらの解決策のかなりの数を自分で調べました。ただし、これらには独自の問題があり、動作がわずかに異なります。通常は、とにかく CSS クラスを切り替えるだけです。さらに、必要がないのに、なぜ Javascript を使用するのでしょうか。

:hover のみを使用するソリューションを見つけることに興味がありましたが、これが (jsbin)です。:hover を追加する要素に置く代わりに、その新しい要素を含み、同じ物理スペースを占有する既存の要素に置きます。この場合、サムネイルと新しい大きな画像の両方を含む div (ホバーされていない場合、div とサムネイルと同じサイズになります)。これは私のユースケースにかなり固有のように思えますが、一般的には、新しい要素と同じサイズの配置された div を使用して実現できる可能性があります。

追加: この回答の作成が完了した後、pozs は基本的に上記と同じソリューションを提供しました!

これと完全な Javascript ソリューションの 1 つとの間の妥協点は、新しい要素を追加するときに Javascript/DOM ホバー イベントに効果的に依存する 1 回限りのクラスを用意し、それをすべて削除して :hover に依存することです。 . これは、Jordan Gray が提供するソリューションです(Jsbin)

これらは両方とも、私が試したすべてのブラウザーで動作します: Chrome、Firefox、Opera、Safari、および Internet Explorer。

于 2012-11-06T21:05:51.747 に答える
0

:hover宣言がマウスのわずかな動きでのみトリガーされる理由は100%わかりません。考えられる理由は、技術的には要素を実際にホバーしない可能性があることです。基本的に、ロード中にカーソルの下に要素を押し込みます(大きな画像が完全にロードされるまで、A要素はdisplay: noneその状態にあるため、不可能になる可能性があります:hover)。同時に、それは小さい画像との違いを説明していません...

したがって、回避策は、JavaScriptを使用し、:hoverステートメントを方程式から除外することです。ホバー状態に応じて2つの異なる要素をユーザーに表示するだけIMGです(JavaScriptで切り替えます)。追加の利点として、画像をブラウザで動的に拡大縮小する必要はありません(Chromeの視覚的な不具合)。

http://jsbin.com/ifitep/34/を参照してください

更新.active:JavaScriptを使用して大きな画像にクラスを追加することにより、ネイティブCSSアニメーションを引き続き使用することが完全に可能になります。http://jsbin.com/ifitep/48を参照してください

于 2012-11-05T18:57:13.300 に答える
0

あなたはそのようなことをすることができます: http://jsfiddle.net/jR5Ba/5/

要約すると、画像の前にローディング レイアウトを追加し、大きな画像を含む div を.load()コールバックとともに追加して、ローディング レイヤーを削除します。

上記のフィドルは時間がないため単純化およびクリーンアップされていませんが、必要に応じて明日も作業を続けることができます。

$imageContainer = $("#image-container");    
$image = $('#image');

$imageContainer.on({
    mouseenter: function (event) {    
       //Add a loading class
       $imageContainer.addClass('loading');
       $image.css('opacity',0.5); 

       //Insert div (for styling) containing large image            
       $(this).append('<div><img class="hidden large-image-container" id="'+this.id+'-large" src="'+fullimageurl+'" /></div>');

       //Append large image load callback            
       $('#'+this.id+'-large').load(function() {
           $imageContainer.removeClass('loading');
           $image.css('opacity',1);
           $(this).slideDown('slow');
           //alert ("The image has loaded!");        
       });
    },            
    mouseleave: function (event) {
       //Remove loading class
       $imageContainer.removeClass('loading');
       //Remove div with large image 
       $('#'+this.id+'-large').remove();
       $image.css('opacity',1);             
    }        
});

編集

これは、大きな画像が表示されたときのアニメーション付きの適切なサイズの読み込みレイヤーを含む新しいバージョンのフィドルです: http://jsfiddle.net/jR5Ba/6/

それが役立つことを願っています

于 2012-10-31T20:54:46.387 に答える
0

ダウンロードする画像ができるまで、IMG タグを DOM に追加しないでください。そうすれば、画像が読み込まれるまで Load イベントは発生しません。修正されたJSは次のとおりです。

$(function () {

    var fullimageurl = 'http://upload.wikimedia.org/wikipedia/commons/3/32/Cairo_International_Stadium.jpg';

    var fullimage = $('<img/>')
        .addClass('kiyuras-image')
        .load(function () {
            anchor.show(); // Only happens after IMG src has loaded
        });

    var anchor = $('<a/>').hide();

    $('body').prepend(anchor);

    $("#image").on('mouseenter', function () {
        fullimage.attr('src',fullimageurl); // IMG has source
        $(this).off('mouseenter');
        anchor.append(fullimage); // Append IMG to DOM now.
    });

});
于 2012-11-02T22:52:59.027 に答える
0

あなたの質問のこの部分から:「画像がすばやく読み込まれるかキャッシュされている場合、これはうまく機能しますが、画像全体の読み込みに時間がかかり、読み込み中にマウスを動かさない場合」

最初にすべての画像を JavaScript で「プリロード」する価値はありますか。これにより、すべての画像が最初に正常にロードされる可能性があり、接続が遅い人にとってはもう少しユーザーフレンドリーになる可能性があります.

于 2012-10-29T11:30:39.570 に答える
0

私はそれを行い、Chrome(バージョン22.0.1229.94 m)で動作しました:CSSを次のように変更しました:

.kiyuras-image{
    position: absolute;
    top: 8px;
    left: 8px;
    max-width: 400px;
}
.not-hovered{
    max-width: 220px;
}

スクリプトは次のようになります。

$(function(){
    var fullimageurl = 'http://upload.wikimedia.org/wikipedia/commons/3/32/Cairo_International_Stadium.jpg';

    var fullimage = $('<img/>')
        .addClass('kiyuras-image')
        .load(function () {
            anchor.show();
        });

    var anchor = $('<a/>').hide().append(fullimage);

    $('body').prepend(anchor);

    $('.kiyuras-image').on('mouseout',function(){
        $(this).addClass('not-hovered');
    });
    $('.kiyuras-image').on('mouseover',function(){
        $(this).removeClass('not-hovered');
    });

    $("#image").one('mouseover', function(){
        fullimage.attr('src',fullimageurl);
    });
});

基本的に、「ホバー」ステータスの検出/レンダリングにおけるChromeのバグだと思います。実際、cssを次のように単純に変更しようとしたとき:

.kiyuras-image{
    position: absolute;
    top: 8px;
    left: 8px;
    max-width: 400px;
}
.kiyuras-image:not(:hover) {
    position: absolute;
    top: 8px;
    left: 8px;
    max-width: 220px;
}

それでもうまくいきませんでした。

PS: 私の英語で申し訳ありません。

于 2012-11-06T15:59:56.030 に答える