Javascript 如何在支持触摸的浏览器中通过触摸模拟悬停?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2851663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I simulate a hover with a touch in touch enabled browsers?
提问by Rich Bradshaw
With some HTML like this:
使用一些像这样的 HTML:
<p>Some Text</p>
Then some CSS like this:
然后一些像这样的CSS:
p {
color:black;
}
p:hover {
color:red;
}
How can I allow a long touch on a touch enabled device to replicate hover? I can change markup/use JS etc, but can't think of an easy way to do this.
如何允许在启用触摸的设备上长按以复制悬停?我可以更改标记/使用 JS 等,但想不出一种简单的方法来做到这一点。
回答by Rich Bradshaw
OK, I've worked it out! It involves changing the CSS slightly and adding some JS.
好的,我已经解决了!它涉及稍微更改 CSS 并添加一些 JS。
Using jQuery to make it easy:
使用 jQuery 使其变得简单:
$(document).ready(function() {
$('.hover').on('touchstart touchend', function(e) {
e.preventDefault();
$(this).toggleClass('hover_effect');
});
});
In english: when you start or end a touch, turn the class hover_effecton or off.
英语:当您开始或结束触摸时,打开hover_effect或关闭课程。
Then, in your HTML, add a class hover to anything you want this to work with. In your CSS, replace any instance of:
然后,在您的 HTML 中,将一个类悬停添加到您希望它使用的任何内容上。在您的 CSS 中,替换以下任何实例:
element:hover {
rule:properties;
}
with
和
element:hover, element.hover_effect {
rule:properties;
}
And just for added usefulness, add this to your CSS as well:
并且只是为了增加实用性,也将它添加到您的 CSS 中:
.hover {
-webkit-user-select: none;
-webkit-touch-callout: none;
}
To stop the browser asking you to copy/save/select the image or whatever.
停止浏览器要求您复制/保存/选择图像或其他任何内容。
Easy!
简单!
回答by Razvan Cercelaru
All you need to do is bind touchstart on a parent. Something like this will work:
您需要做的就是在父级上绑定 touchstart。像这样的事情会起作用:
$('body').on('touchstart', function() {});
You don't need to do anything in the function, leave it empty. This will be enough to get hovers on touch, so a touch behaves more like :hover and less like :active. iOS magic.
你不需要在函数中做任何事情,把它留空。这足以在触摸时获得悬停,因此触摸的行为更像 :hover 而不太像 :active。iOS 魔法。
回答by Anselm
Try this:
尝试这个:
<script>
document.addEventListener("touchstart", function(){}, true);
</script>
And in your CSS:
在你的 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*/
}
With this code you don't need an extra .hover class!
使用此代码,您不需要额外的 .hover 类!
回答by Mathias Bynens
To answer your main question: “How do I simulate a hover with a touch in touch enabled browsers?”
回答您的主要问题:“如何在支持触摸的浏览器中通过触摸来模拟悬停?”
Simply allow ‘clicking' the element (by tapping the screen), and then trigger the hoverevent using JavaScript.
只需允许“点击”元素(通过点击屏幕),然后hover使用 JavaScript触发事件。
var p = document.getElementsByTagName('p')[0];
p.onclick = function() {
// Trigger the `hover` event on the paragraph
p.onhover.call(p);
};
This should work, as long as there's a hoverevent on your device (even though it normally isn't used).
只要hover您的设备上有事件(即使通常不使用它),这应该可以工作。
Update:I just tested this technique on my iPhone and it seems to work fine. Try it out here: http://jsfiddle.net/mathias/YS7ft/show/light/
更新:我刚刚在我的 iPhone 上测试了这项技术,它似乎工作正常。在这里试试:http: //jsfiddle.net/mathias/YS7ft/show/light/
If you want to use a ‘long touch' to trigger hover instead, you can use the above code snippet as a starting point and have fun with timers and stuff ;)
如果您想使用“长按”来触发悬停,您可以使用上面的代码片段作为起点,并享受计时器之类的乐趣;)
回答by Alexandre Rosário
Further Improved Solution
进一步改进的解决方案
First I went with the Rich Bradshaw's approach, but then problems started to appear. By doing the e.preventDefault()on 'touchstart'event, the page no longer scrolls and, neither the long press is able to fire the options menu nor double click zoom is able to finish executing.
首先我采用了Rich Bradshaw 的方法,但随后问题开始出现。通过在'touchstart'事件上执行e.preventDefault(),页面不再滚动,长按既不能触发选项菜单,也不能双击缩放完成执行。
A solution could be finding out which event is being called and just e.preventDefault()in the later one, 'touchend'. Since scroll's 'touchmove'comes before 'touchend'it stays as by default, and 'click'is also prevented since it comes afterwords in the event chain applied to mobile, like so:
溶液可以找出哪些事件被称为,只是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');
});
But then, when options menu appears, it no longer fires 'touchend'responsible for toggling off the class, and next time the hover behavior will be the other way around, totally mixed up.
但是,当出现“选项”菜单时,它不再触发“触摸”负责切换课程,然后下次悬停行为将是另一个方式,完全混合。
A solution then would be, again, conditionally finding out which event we're in, or just doing separate ones, and use addClass()and removeClass()respectively on 'touchstart'and 'touchend', ensuring it always starts and ends by respectively adding and removing instead of conditionally deciding on it. To finish we will also bind the removing callback to the 'focusout'event type, staying responsible for clearing any link's hover class that might stay on and never revisited again, like so:
一个解决方案是,再次有条件地找出我们在哪个事件中,或者只是做单独的事件,并分别在'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');
});
Atention:Some bugs still occur in the two previous solutions and, also think (not tested), double click zoom still fails too.
注意:前两个解决方案中仍然存在一些错误,并且还认为(未测试),双击缩放仍然失败。
Tidy and Hopefully Bug Free (not :)) Javascript Solution
整洁并希望没有错误(不是 :))Javascript 解决方案
Now, for a second, cleaner, tidier and responsive, approach just using javascript (no mix between .hover class and pseudo :hover) and from where you could call directly your ajax behavior on the universal (mobile and desktop) 'click'event, I've found a pretty well answered questionfrom which I finally understood how I could mix touch and mouse events together without several event callbacks inevitably changing each other's ones up the event chain. Here's how:
现在,使用 javascript(.hover 类和伪 :hover 之间没有混合)的第二个,更干净,更整洁和响应式的方法,并且您可以从那里直接调用通用(移动和桌面)'click'事件上的 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!
}
});
回答by sijo vijayan
The mouse hovereffect cannot be implemented in touch device . When I'm appeared with same situation in safariiosI used :activein css to make effect.
鼠标hover效果无法在触控设备中实现。当我在css中safariios使用相同的情况出现时:active。
ie.
IE。
p:active {
color:red;
}
In my case its working .May be this is also the case that can be used with out using javascript. Just give a try.
在我的情况下它的工作。可能也是这种情况可以在不使用 javascript 的情况下使用。试试吧。
回答by l00k
Add this code and then set class "tapHover" to elements which you would like to work this way. First time you tap an element it will gain pseudoclass ":hover" and class "tapped". Click event will be prevented. Second time you tap the same element - click event will be fired.
添加此代码,然后将类“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>
回答by pimbrouwers
My personal taste is to attribute the :hoverstyles to the :focusstate as well, like:
我个人的喜好是将:hover样式也归因于:focus状态,例如:
p {
color: red;
}
p:hover, p:focus {
color: blue;
}
Then with the following HTML:
然后使用以下 HTML:
<p id="some-p-tag" tabindex="-1">WOOOO</p>
And the following JavaScript:
以及以下 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();
}
});
回答by drawnonward
One way to do it would be to do the hover effect when the touch starts, then remove the hover effect when the touch moves or ends.
一种方法是在触摸开始时执行悬停效果,然后在触摸移动或结束时移除悬停效果。
This is what Apple has to say about touch handlingin general, since you mention iPhone.
既然你提到了 iPhone,这就是 Apple 对触摸处理的一般看法。
回答by Joonas Trussmann
Without device (or rather browser) specific JS I'm pretty sure you're out of luck.
如果没有设备(或者更确切地说是浏览器)特定的 JS,我很确定你不走运。
Edit: thought you wanted to avoid that until i reread your question. In case of Mobile Safari you can register to get all touch events similar to what you can do with native UIView-s. Can't find the documentation right now, will try to though.
编辑:以为你想避免这种情况,直到我重读你的问题。在 Mobile Safari 的情况下,您可以注册以获取与使用本机 UIView-s 可以执行的操作类似的所有触摸事件。现在找不到文档,但会尝试。

