处理触摸屏上的悬停事件[关闭]

Posted

技术标签:

【中文标题】处理触摸屏上的悬停事件[关闭]【英文标题】:Handling Hover Events on a Touch Screen [closed] 【发布时间】:2014-01-16 02:50:09 【问题描述】:

我设计的一个网站使用了一个导航菜单,它在 :hover 上显示子菜单。最初的网站没有使用任何响应式设计:它只针对桌面环境。我现在使用响应式设计技术来定位移动设备和平板电脑,其中许多是基于触摸而不是基于鼠标的。

我面临的最大问题(许多其他人似乎也面临过)是基于悬停的导航菜单:它在鼠标环境中运行良好,但在触摸设备上,没有可靠的方法来触发悬停,使页面难以使用。

目标是这样的:

    当鼠标悬停在菜单上时,显示子菜单。 当用鼠标单击菜单时,打开锚标记的链接。 第一次通过触摸单击菜单时,显示子菜单。 第二次通过触摸单击菜单时,打开锚标记的链接。 为也连接了鼠标设备的平板电脑无缝切换功能。

我的团队不愿意在基于鼠标的机器上牺牲悬停效果。他们喜欢它,不想让菜单基于所有设备点击。我同意这一点。

环顾网络后,我找不到任何单一的解决方案来解决我的问题。我将其中的一些放在一起,开发了一些在 android 上经过良好测试的东西,得到了我想要的功能。有什么可以改进的和/或您认为这种方法有什么问题吗?

jQuery(document).ready(function() 
    var touched=false;
    jQuery(".nav").on('touchstart', 'li .has_children', function (e)   touched=true; );
    jQuery("html").on('mousemove', function (e)  touched=false; );

    jQuery("html").on('click', updatePreviousTouched );

    jQuery(".nav").on('click', 'li .has_children', function (e) 
        updatePreviousTouched(e);
        if( touched )  
            if (jQuery(this).data('clicked_once')) 
                jQuery(this).data('clicked_once', false);
                return true;
             else 
                e.preventDefault();
                jQuery(this).trigger("mouseenter"); 
                jQuery(this).data('clicked_once', true);

            
        
        touched=false;
    ); 

    var previous_touched;
    function updatePreviousTouched(e) 
        if( typeof previous_touched != 'undefined' && previous_touched != null && !previous_touched.is( jQuery(e.target) ) ) 
            previous_touched.data('clicked_once', false);
        
        previous_touched=jQuery(e.target);
    

这是一个 jfiddle:http://jsfiddle.net/5FfCF/1/

如果此解决方案可以改进,请提供任何建议。如果您发现它对您不起作用,也请告诉我。我在这里发布它是为了尝试获得任何改进建议并发布这个想法,以便其他人可以从中受益。

这是我目前的测试结果:

    Windows 7 在主要 5 种浏览器上:有效。 默认浏览器上的 Android 平板电脑:有效。 在 IE 和 Chrome 上带有触摸屏的 Windows 7 笔记本电脑:工作排序。该机器正在运行两种浏览器的桌面版本,因此它不会触发“touchstart”事件。在触摸屏和浏览器之间的某个地方,有些东西正在将触摸转换为鼠标事件。但是,由于鼠标是该设备的不可拆卸部分,我不认为这是失败的。如果它像平板电脑一样工作,我会喜欢它,但似乎还没有可用的技术。 iOS iPad:这在我编写上面的 javascript 之前 可以正常工作。 ios 似乎在幕后为我们做了一些悬停/点击魔术。我有一个团队成员检查我的 javascript 是否破坏了 iOS 功能,一旦我得到答案,我将编辑这篇文章。

其他说明:

    这只是桌面和平板电脑站点的菜单。移动网站有一个不同的基于点击的菜单。我不建议将此解决方案用于手机大小的设备。

【问题讨论】:

这个问题似乎是题外话,因为它是一个代码审查请求。这更适合codereview.stackexchange.com 大声笑,我被那该死的东西吞没了。这个网站我发誓它比破解更糟糕。 【参考方案1】:

Piddle Diddle Fiddle :)


Fiddle Embedded Demo (use with phone for easiest access)


在阅读这堵文字墙之前,请先检查一下小提琴并确保它是您正在寻找的。也在手机上测试(我在我的 Android 上测试过,没有任何问题)。

如果您有一套完全独立的手机代码,那么您真的没有什么可担心的。适应触摸与悬停事件在 iOS 设备上特别棘手。但是我能够通过捕获一系列转换为触摸事件的鼠标事件来克服这个问题。

对于您的特殊情况,由于您希望这三者之间如此不同,我建议您运行早期脚本来获取屏幕尺寸,如果它小于### px x ### px,请添加一个名为handheld 或@ 的类987654326@ 或body。现在您所要做的就是将touch 捕获代码分配给$('.mobile .nav'),并有一段单独的代码将hover 事件分配给PC。

对于平板电脑,您必须决定什么对您更重要 - 能够使用每个菜单的根菜单项进行点击和导航,或者只允许点击子菜单项(这样就无需将.mobile 类添加到body)。

这里有一些您应该可以在移动设备和桌面设备上使用的代码。

jQuery:

jQuery(document).ready(function () 
    $('.nav').on('click mousedown mouseup touchstart touchmove', 'a.has_children', function () 
        if ( $(this).next('ul').hasClass('open') && !$(this).parents('ul').hasClass('open')) 
            $('.open').removeClass('open');
            return false;
        
        $('.open').not($(this).parents('ul')).removeClass('open');
        $(this).next('ul').addClass('open');
        return false;
    );
    $(document).on('click', ':not(.has_children, .has_children *)', function()         
        if( $('.open').length > 0 ) 
            $('.open').removeClass('open');
            return false;
        
    );
);

通常我不会像我将要做的那样复制所有的 HTML,但在这个特殊的例子中,你需要完全按照我在这里的方式来使用它,以避免 inline-block 空白故障.将我的小提琴与您的原作进行比较,看看悬停/单击每个链接有多容易。

HTML:

<div class="header-nav-menu">
    <ul class="nav">
        <li><a href="http://www.google.com">One</a></li><li>
        <a class="has_children" href="http://www.google.com">Two</a>
            <ul>
                <li><a href="http://www.google.com">2A</a></li><li>
                <a href="http://www.google.com">2B</a>

                </li>
                <li><a href="http://www.google.com">2C</a>

                </li>
            </ul>
        </li><li>
        <a class="has_children" href="http://www.google.com">Three</a>
            <ul>
                <li><a href="http://www.google.com">3A</a>

                </li>
                <li> <a class="has_children" href="http://www.google.com">3B</a>

                    <ul>
                        <li><a href="http://www.google.com">3BI</a>

                        </li>
                        <li><a href="http://www.google.com">3BII</a>

                        </li>
                        <li><a href="http://www.google.com">3BIII</a>

                        </li>
                    </ul>
                </li>
                <li><a href="http://www.google.com">3C</a>

                </li>
            </ul>
        </li><li>
        <a href="http://www.google.com">Four</a></li><li>
        <a href="http://www.google.com">Five</a></li>
    </ul>
</div>

很确定我什至没有碰过 CSS,所以我暂时把它留在 Fiddle 中。希望这对您有所帮助。

【讨论】:

这个答案看起来很棒,非常感谢。我还没有能够测试,但我还是想说谢谢你这么多的努力。 尽我所能提供帮助! :D Deryck:看起来他们已经搁置了这个问题。我在这里发布了这个问题:codereview.stackexchange.com/questions/38239/…。您能否在此处重新发布您的答案,以便我对其进行投票、测试,然后在可行时接受它?

以上是关于处理触摸屏上的悬停事件[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何识别鼠标悬停事件对象是不是来自触摸屏触摸?

触摸屏设备上的 CSS 悬停不会被忽略

使用 CSS3 触摸事件的悬停效果

CSS:触摸屏设备上的悬停行为

jquery防止触摸悬停功能

JavaScript 切换桌面/移动设备的悬停/触摸事件