web-dev-qa-db-ja.com

タッチ対応ブラウザーでタッチしたホバーをシミュレートするにはどうすればよいですか?

次のようなHTMLの場合:

<p>Some Text</p>

次に、このようないくつかのCSS:

p {
  color:black;
}

p:hover {
  color:red;
}

タッチ対応デバイスでロングタッチを許可してホバーを複製するにはどうすればよいですか? JSなどのマークアップを変更できますが、これを行う簡単な方法は考えられません。

118
Rich Bradshaw

OK、うまくいきました! CSSをわずかに変更し、JSを追加する必要があります。

JQueryを使用して簡単に:

$(document).ready(function() {
    $('.hover').on('touchstart touchend', function(e) {
        e.preventDefault();
        $(this).toggleClass('hover_effect');
    });
});

英語:タッチを開始または終了するときに、クラスhover_effectをオンまたはオフにします。

次に、HTMLで、これに使用したいものにクラスホバーを追加します。 CSSで、次のインスタンスを置き換えます。

element:hover {
    rule:properties;
}

element:hover, element.hover_effect {
    rule:properties;
}

また、有用性を高めるために、これもCSSに追加します。

.hover {
-webkit-user-select: none;
-webkit-touch-callout: none;        
}

画像などをコピー/保存/選択するよう求めるブラウザを停止します。

簡単!

170
Rich Bradshaw

必要なのは、親にタッチスタートをバインドすることだけです。このような何かが動作します:

$('body').on('touchstart', function() {});

関数で何もする必要はありません。空のままにします。これはタッチでホバリングするのに十分であるため、タッチは:hoverのように動作し、:activeのように動作しません。 iOSの魔法。

52

これを試して:

<script>
document.addEventListener("touchstart", function(){}, true);
</script>

そして、あなたのCSSで:

element:hover, element:active {
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
-webkit-touch-callout: none /*only to disable context menu on long press*/
}

このコードを使用すると、追加の.hoverクラスは必要ありません!

40
Anselm

あなたの主な質問に答えるには:「タッチ対応ブラウザのタッチでホバーをシミュレートするにはどうすればよいですか?」

(画面をタップすることで)要素の「クリック」を許可し、JavaScriptを使用してhoverイベントをトリガーします。

var p = document.getElementsByTagName('p')[0];
p.onclick = function() {
 // Trigger the `hover` event on the paragraph
 p.onhover.call(p);
};

これは、デバイスでhoverイベントが発生している限り機能します(通常は使用されませんが)。

更新: iPhoneでこの手法をテストしたところ、うまく機能しているようです。ここで試してみてください: http://jsfiddle.net/mathias/YS7ft/show/light/

代わりに「ロングタッチ」を使用してホバーをトリガーする場合は、上記のコードスニペットを開始点として使用し、タイマーなどを楽しんでください;)

25
Mathias Bynens

さらに改善されたソリューション

最初にRich Bradshawのアプローチを使用しましたが、問題が発生し始めました。 e.preventDefault() 'touchstart'イベントで実行すると、ページはスクロールしなくなり、長押しもオプションメニューを起動したり、ズームをダブルクリックしたりすると、実行を終了できます。

解決策は、どのイベントが呼び出されているかを見つけることであり、後のイベントではちょうどe.preventDefault() 'touchend' 。スクロールの 'touchmove' 'touchend'の前に来るため、デフォルトのままで、 'click 'は、次のようにモバイルに適用されるイベントチェーンの後に続くため、防止されます。

// Binding to the '.static_parent' ensuring dynamic ajaxified content
$('.static_parent').on('touchstart touchend', '.link', function (e) {

    // If event is 'touchend' then...
    if (e.type == 'touchend') {
        // Ensuring we event prevent default in all major browsers
        e.preventDefault ? e.preventDefault() : e.returnValue = false;
    }

    // Add class responsible for :hover effect
    $(this).toggleClass('hover_effect');
});

しかし、その後、オプションメニューが表示されると、クラスを切り替えるオフ 'touchend'が発生しなくなり、次回ホバー動作が逆になり、完全に混乱します。

解決策は、再び、条件付きでどのイベントに参加しているかを見つけるか、単に別々のイベントを実行して、addClass()およびremoveClassを使用することです()それぞれ 'touchstart'および 'touchend'、それぞれ追加して常に開始および終了することを保証する条件付きで決定する代わりに削除します。終了するために、削除コールバックを 'focusout'イベントタイプにバインドし、リンクのホバークラスをクリアする責任を維持します。

$('.static_parent').on('touchstart', '.link', function (e) {
    $(this).addClass('hover_effect');
});

$('.static_parent').on('touchend focusout', '.link', function (e) {
    // Think double click zoom still fails here
    e.preventDefault ? e.preventDefault() : e.returnValue = false;
    $(this).removeClass('hover_effect');
});

注意:いくつかのバグは以前の2つのソリューションでまだ発生しており、ダブルクリックズームも失敗します(テストされていません)。

きちんとした、うまくいけばバグフリー(ではない:))JavaScriptソリューション

Now、2番目の、よりクリーンで、整頓された、レスポンシブな、javascriptを使用するアプローチ(.hoverクラスとpseudo:hoverの混在なし)と、直接ajax動作を呼び出すことができる場所ユニバーサル(モバイルとデスクトップ) 'click'イベントで、私は かなりよく回答された質問 を見つけました。いくつかのイベントコールバックが必然的にイベントチェーン内で互いのイベントを変更することなく、タッチイベントとマウスイベントが一緒になります。方法は次のとおりです。

$('.static_parent').on('touchstart mouseenter', '.link', function (e) {
    $(this).addClass('hover_effect');
});

$('.static_parent').on('mouseleave touchmove click', '.link', function (e) {
    $(this).removeClass('hover_effect');

    // As it's the chain's last event we only prevent it from making HTTP request
    if (e.type == 'click') {
        e.preventDefault ? e.preventDefault() : e.returnValue = false;

        // Ajax behavior here!
    }
});
13

マウスhover効果はタッチデバイスに実装できません。 safariiosに同じ状況で登場したとき、CSSで:activeを使用して有効にしました。

すなわち。

p:active {
  color:red;
}

私の場合、それが機能します。これは、javascriptを使用せずに使用できる場合でもあります。試してみてください。

3
sijo vijayan

このコードを追加して、クラス「tapHover」をこの方法で作業する要素に設定します。エレメントを初めてタップすると、擬似クラス「:hover」とクラス「tapped」が取得されます。クリックイベントは防止されます。もう一度同じ要素をタップすると、クリックイベントが発生します。

// Activate only in devices with touch screen
if('ontouchstart' in window)
{
    // this will make touch event add hover pseudoclass
    document.addEventListener('touchstart', function(e) {}, true);

    // modify click event
    document.addEventListener('click', function(e) {
        // get .tapHover element under cursor
        var el = jQuery(e.target).hasClass('tapHover')
            ? jQuery(e.target)
            : jQuery(e.target).closest('.tapHover');

        if(!el.length)
            return;

        // remove tapped class from old ones
        jQuery('.tapHover.tapped').each(function() {
            if(this != el.get(0))
                jQuery(this).removeClass('tapped');
        });

        if(!el.hasClass('tapped'))
        {
            // this is the first tap
            el.addClass('tapped');
            e.preventDefault();
            return false;
        }
        else
        {
            // second tap
            return true;
        }
    }, true);
}
.box {
        float:          left;
        
        display:        inline-block;
        margin:         50px 0 0 50px;
        width:          100px;
        height:         100px;
        overflow:       hidden;
        
        font-size:      20px;
        
        border:         solid 1px black;
}
.box.tapHover {
        background:     yellow;
}
.box.tapped {
        border:         solid 3px red;
}
.box:hover {
        background:     red;
}
<div class="box" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
2
l00k

その方法の1つは、タッチが開始されたときにホバー効果を実行し、タッチが移動または終了したときにホバー効果を削除することです。

これはAppleが タッチ処理 について言っていることです。あなたがiPhoneに言及しているからです。

1
drawnonward

デバイス(またはブラウザー)固有のJSがなければ、あなたは運が悪いと確信しています。

編集:あなたの質問を読み直すまで、あなたはそれを避けたいと思った。 Mobile Safariの場合、ネイティブUIView-sでできることと同様に、すべてのタッチイベントを取得するために登録できます。すぐにドキュメントを見つけることができませんが、しようとします。

1

私の個人的な趣味は、次のように:hoverスタイルを:focus状態にも関連付けることです。

p {
    color: red;
}

p:hover, p:focus {
    color: blue;
}

次に、次のHTMLを使用します。

<p id="some-p-tag" tabindex="-1">WOOOO</p>

そして、次のJavaScript:

$("#some-p-tag").on("touchstart", function(e){
    e.preventDefault();
    var $elem = $(this);

    if($elem.is(":focus")) {
        //this can be registered as a "click" on a mobile device, as it's a double tap
        $elem.blur()
    }
    else {
        $elem.focus();
    }
});
1
pim

ネイティブJavascriptとjQueryの組み合わせ:

var gFireEvent = function (oElem,sEvent) 
{
 try {
 if( typeof sEvent == 'string' && o.isDOM( oElem ))
 {
  var b = !!(document.createEvent),
     evt = b?document.createEvent("HTMLEvents"):document.createEventObject();
  if( b )    
  {  evt.initEvent(sEvent, true, true ); 
    return !oElem.dispatchEvent(evt);
  }
  return oElem.fireEvent('on'+sEvent,evt);
 }
 } catch(e) {}
 return false;
};


// Next you can do is (bIsMob etc you have to determine yourself):

   if( <<< bIsMob || bIsTab || bisTouch >>> )
   {
     $(document).on('mousedown', function(e)
     {
       gFireEvent(e.target,'mouseover' );
     }).on('mouseup', function(e)
     {
       gFireEvent(e.target,'mouseout' );
     });
   }
0
Codebeat

私が見つけた最も簡単な解決策::hover cssルールを含む<span>タグがいくつかありました。 <a href = "javascript:void(0)">とvoilàに切り替えました。 iOSのホバースタイルが機能し始めました。

0
Becario Senior

Solved 2019-Hover on Touch

一般的に、iOSまたはタッチでホバーを完全に使用することは避けるのが最善のようです。以下のコードは、タッチが維持され、他のiOSフライアウトがない限り、CSSを適用します。これを行う;

  1. Jquery add:$( "p")。on( "touchstart"、function(e){$(this).focus(); e.preventDefault();});

  2. CSS:p:hoverをp:focusに置き換え、p:activeを追加します

オプション;

  • jquery pセレクターを任意のクラスなどに置き換えます

  • 効果を維持するには、p:hoverも保持し、body {cursor:ponter;}を追加して、どこでもタップして終了するようにします

  • 同じコードでクリック&マウスオーバーイベントとタッチスタートを試してください(ただし、テストされていません)

  • e.preventDefault();を削除します。ユーザーがiOSフライアウトを使用できるようにする(コピーなど)

ノート

  • テキスト要素についてのみテストされ、iosは入力などを異なる方法で処理する場合があります

  • safariまたはChromeを使用して、iphone XR ios 12.1.12およびipad 3 ios 9.3.5でのみテストされています。

0
darren

使用もCSSを使用し、フォーカスとアクティブ(IE7以下の場合)を非表示リンクに追加できます。クラスメニューのあるdiv内のulメニューの例:

.menu ul ul {display:none; position:absolute; left:100%; top:0; padding:0;}
.menu ul ul ul {display:none; position:absolute; top:0; left:100%;}
.menu ul ul a, .menu ul ul a:focus, .menu ul ul a:active { width:170px; padding:4px 4%; background:#e77776; color:#fff; margin-left:-15px; }
.menu ul li:hover > ul { display:block; }
.menu ul li ul li {margin:0;}

それは遅く、テストされていません、動作するはずです;-)

0
Mark Groen