我编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种方法可以用JavaScript来检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它适用于iOS, Android等,但我也想根据用户的设备是否有触摸屏来编写条件语句。

这可能吗?


当前回答

我认为最好的方法是:

var isTouchDevice =
    (('ontouchstart' in window) ||
    (navigator.maxTouchPoints > 0) ||
    (navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
    /* Code for touch device /*
}else{
    /* Code for non touch device */
}

其他回答

所以关于检测触摸/非触摸设备存在很大的争议。窗口平板电脑的数量和尺寸都在增加,这给我们网页开发者带来了另一个难题。

我已经使用并测试了blmstr的菜单答案。菜单的工作方式是这样的:当页面加载时,脚本检测这是一个触摸或非触摸设备。基于此,菜单将在悬停(非触摸)或点击/点击(触摸)时工作。

在大多数情况下,blmstr的脚本似乎工作得很好(特别是2018年的那个)。但仍然有一种设备,当它不是触摸时,它会被检测为触摸,反之亦然。

出于这个原因,我做了一些挖掘,多亏了这篇文章,我从blmstr的第4个脚本中替换了几行:

函数is_touch_device4() { If ("ontouchstart" in window) 返回true; 如果窗口。DocumentTouch的文档实例) 返回true; 返回窗口。matchMedia("(指针:粗)").matches; } alert('Is touch device: '+is_touch_device4()); console.log('Is touch device: '+is_touch_device4());

由于封锁,有有限的触摸设备来测试这一个,但到目前为止,上面的工作很好。

如果任何人有桌面触摸设备(如平板电脑)可以确认脚本是否工作正常,我将不胜感激。

现在在支持指针方面:粗媒体查询似乎是支持的。我保留了上面的行,因为我在移动firefox上(出于某种原因)出现了问题,但媒体查询上面的行是有效的。

谢谢

当连接鼠标时,可以假设有相当高的点击率(我想说几乎100%),用户在页面准备好后移动鼠标至少一小段距离-没有任何点击。下面的机制检测到这一点。如果检测到,我认为这是缺少触摸支持的标志,或者,如果支持,在使用鼠标时不太重要。如果未检测到触摸设备,则假定为触摸设备。

这种方法可能不适合所有目的。它可以用来控制基于加载页面上的用户交互激活的功能,例如图像查看器。下面的代码还将把mouemove事件绑定在没有鼠标的设备上,因为它现在很突出。其他方法可能更好。

大致是这样的(对jQuery来说很抱歉,但在纯Javascript中类似):

var mousedown, first, second = false;
var ticks = 10;
$(document).on('mousemove', (function(e) {
    if(UI.mousechecked) return;
    if(!first) {
        first = e.pageX;
        return;
        }
    if(!second && ticks-- === 0) {
        second = e.pageX;
        $(document).off('mousemove'); // or bind it to somewhat else
        }
    if(first  && second  && first !== second && !mousedown){
        // set whatever flags you want
        UI.hasmouse = true;
        UI.touch = false;
        UI.mousechecked = true;
    }

    return;
}));
$(document).one('mousedown', (function(e) {
    mousedown = true;
    return;
}));
$(document).one('mouseup', (function(e) {
    mousedown = false;
    return;
}));

我使用上面的代码片段来检测是否有触摸,所以我的iframe会在台式电脑上显示,而不是在触摸时显示。我注意到Android 4.0的Opera Mini在单独使用blmstr代码时仍然注册为非触摸设备。(有人知道为什么吗?)

我最终使用:

<script>
$(document).ready(function() {
    var ua = navigator.userAgent;
    function is_touch_device() { 
        try {  
            document.createEvent("TouchEvent");  
            return true;  
        } catch (e) {  
            return false;  
        }  
    }

    if ((is_touch_device()) || ua.match(/(iPhone|iPod|iPad)/) 
    || ua.match(/BlackBerry/) || ua.match(/Android/)) {
        // Touch browser
    } else {
        // Lightbox code
    }
});
</script>

试图检测触控的最大“陷阱”是同时支持触控和触控板/鼠标的混合设备。即使你能够正确地检测用户的设备是否支持触摸,你真正需要做的是检测用户当前使用的输入设备。这里有一份关于这个挑战的详细报告和可能的解决方案。

基本上,判断用户是触摸屏幕还是使用鼠标/触控板的方法是在页面上注册touchstart和mouseover事件:

document.addEventListener('touchstart', functionref, false) // on user tap, "touchstart" fires first
document.addEventListener('mouseover', functionref, false) // followed by mouse event, ie: "mouseover"

触摸动作会触发这两个事件,尽管前者(touchstart)在大多数设备上总是先触发。因此,依靠这个可预测的事件序列,您可以创建一种机制,动态地向文档根添加或删除一个can-touch类,以反映当前用户在文档上的输入类型:

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")
     
    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }
     
    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }
     
    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

详情请点击这里。

我会避免使用屏幕宽度来判断一个设备是否是触控设备。触摸屏比699px大得多,想想Windows 8。Navigatior。userAgent可以很好地覆盖误报。

我建议你在Modernizr上看看这一期。

你是想测试设备是否支持触摸事件,还是一个触摸设备。不幸的是,这不是一回事。