如何使用触控启用的浏览器模拟悬停?

Ric*_*haw 119 html javascript css hover touch

使用这样的HTML:

<p>Some Text</p>
Run Code Online (Sandbox Code Playgroud)

然后一些CSS像这样:

p {
  color:black;
}

p:hover {
  color:red;
}
Run Code Online (Sandbox Code Playgroud)

如何允许长时间触摸启用触摸的设备复制悬停?我可以改变标记/使用JS等,但想不到一个简单的方法来做到这一点.

Ric*_*haw 171

好的,我已经解决了!它涉及稍微改变CSS并添加一些JS.

使用jQuery使其变得简单:

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

在英语中:当您开始或结束触摸时,打开hover_effect或关闭课程.

然后,在HTML中,将类悬停添加到您希望使用的任何内容.在您的CSS中,替换以下任何实例:

element:hover {
    rule:properties;
}
Run Code Online (Sandbox Code Playgroud)

element:hover, element.hover_effect {
    rule:properties;
}
Run Code Online (Sandbox Code Playgroud)

只是为了增加实用性,也可以将它添加到CSS中:

.hover {
-webkit-user-select: none;
-webkit-touch-callout: none;        
}
Run Code Online (Sandbox Code Playgroud)

停止浏览器要求您复制/保存/选择图像或其他任何内容.

简单!

  • 无论如何忽略滚动手势?这正是我所需要的,但现在我无法向上和向下滚动具有此效果的内容. (2认同)

Raz*_*aru 52

您需要做的就是在父级上绑定touchstart.这样的东西会起作用:

$('body').on('touchstart', function() {});
Run Code Online (Sandbox Code Playgroud)

您无需在函数中执行任何操作,请将其留空.这足以让人在触摸时盘旋,因此触摸的行为更像是:悬停而不像:活跃.iOS魔术.

  • 此解决方案是否允许在第二次点击时执行链接? (2认同)

Ans*_*elm 40

试试这个:

<script>
document.addEventListener("touchstart", function(){}, true);
</script>
Run Code Online (Sandbox Code Playgroud)

在你的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*/
}
Run Code Online (Sandbox Code Playgroud)

使用此代码,您不需要额外的.hover类!


Mat*_*ens 25

要回答您的主要问题:"如何通过触摸启用浏览器来模拟悬停?"

只需允许"点击"元素(通过点击屏幕),然后hover使用JavaScript 触发事件.

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

只要hover您的设备上有事件(即使通常不使用),这应该可以工作.

更新:我刚刚在我的iPhone上测试了这种技术,它似乎工作正常.在这里尝试:http://jsfiddle.net/mathias/YS7ft/show/light/

如果你想使用"长触摸"来触发悬停,你可以使用上面的代码片段作为起点,享受定时器和东西的乐趣;)


小智 13

进一步改进的方案

首先,我采用Rich Bradshaw的方法,然后问题开始出现.通过对'touchstart'事件执行e.preventDefault(),页面不再滚动,长按既不能触发选项菜单也不能双击缩放能够完成执行.

一个解决方案可能是找出正在调用的事件,并在后一个事件中找到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');
});
Run Code Online (Sandbox Code Playgroud)

但是,当选项菜单出现时,它不再触发'touchend'负责切换课程,下次悬停行为将是另一种方式,完全混淆.

然后,一个解决方案将有条件地找出我们所处的事件,或者只是单独执行,并分别在'touchstart''touchend'上使用addClass()removeClass (),确保它始终以开始和结束为止分别添加和删除而不是有条件地决定它.为了完成,我们还将删除回调绑定到'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');
});
Run Code Online (Sandbox Code Playgroud)

注意:前两个解决方案中仍然会出现一些错误,并且还认为(未经测试),双击缩放仍然失败.

整洁和希望错误免费(不是:))Javascript解决方案

现在,对于第二个更干净,更整洁,响应更快的方法,只使用javascript(.hover类和伪:悬停之间没有混合),你可以直接调用你在通用(移动和桌面)'点击'事件上的ajax行为,我发现了一个很好的回答问题,我终于明白了如何将触摸和鼠标事件混合在一起而没有几个事件回调不可避免地在事件链中改变彼此的事件.这是如何做:

$('.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!
    }
});
Run Code Online (Sandbox Code Playgroud)