我已经编写了一个可在台式机和移动设备上使用的jQuery插件。我想知道JavaScript是否有办法检测设备是否具有触摸屏功能。我正在使用jquery-mobile.js来检测触摸屏事件,它可以在iOS,Android等系统上运行,但我也想根据用户设备是否具有触摸屏来编写条件语句。

可以吗?

评论

这是document.documentElement中var x ='touchstart'的更好方法; console.log(x)//如果支持则返回true //否则返回false

如果仍然出现新技术,为什么要保护此线程?

#1 楼

更新:在将整个功能检测库引入项目之前,请阅读下面的blmstr答案。检测实际的触摸支持更为复杂,而Modernizr仅涵盖一个基本用例。

Modernizr是一种出色的轻量级方法,可在任何站点上执行各种功能检测。

它只是将每个功能的类添加到html元素中。

然后您可以在CSS和JS中轻松定位这些功能。例如:

html.touch div {
    width: 480px;
}

html.no-touch div {
    width: auto;
}


和Javascript(jQuery示例):

$('html.touch #popup').hide();


评论


Modernizr不会测试触摸屏。它测试浏览器中是否存在触摸事件。请参阅文档中的“其他测试”部分:modernizr.com/docs/#features-misc

–哈里·洛夫(Harry Love)
2012年1月24日17:15



如果(Modernizr.touch){/ *做触摸东西/}其他{/很好,不要* /},您还可以对触摸事件是否存在进行JS测试

–分析家G
2012-02-10 18:27



以@harrylove的观点来说,自Windows 8发布以来,Modernizr一直错误地将我所有PC浏览器返回为兼容触摸屏。

–安东
13年2月18日在15:12

更新:blmstr的答案更好,并且是纯Javascript解决方案。

–艾伦·克里斯托弗·托马斯(Alan Christopher Thomas)
2013年6月17日19:22

如果Modernizr.touch意外返回undefined,则您可能具有自定义的Modernizr(可以选择),而不支持触摸事件检测。

– Henrik N
15年2月24日在7:45

#2 楼

您是否尝试过使用此功能? (这与以前使用的Modernizr相同。)



 function is_touch_device() {  
  try {  
    document.createEvent("TouchEvent");  
    return true;  
  } catch (e) {  
    return false;  
  }  
}

console.log(is_touch_device()); 




UPDATE 1
document.createEvent("TouchEvent")已开始以最新的Chrome(v。17)返回true。 Modernizr前不久对此进行了更新。在此处检查Modernizr测试。
像这样更新您的功能以使其起作用:



 function is_touch_device1() {
  return 'ontouchstart' in window;
}

console.log(is_touch_device1()); 




更新2
我发现以上内容不适用于IE10(在MS Surface上返回false)。解决方法如下:



 function is_touch_device2() {
  return 'ontouchstart' in window        // works on most browsers 
  || 'onmsgesturechange' in window;  // works on IE10 with some false positives
};

console.log(is_touch_device2()); 




UPDATE 3
'onmsgesturechange' in window在某些IE桌面版本中将返回true,因此并不可靠。这样可以更可靠地工作:



 function is_touch_device3() {
  return !!('ontouchstart' in window        // works on most browsers 
  || navigator.maxTouchPoints);       // works on IE10/11 and Surface
};

console.log(is_touch_device3()); 




Update 2018
随着时间的流逝,有更多更好的新方法可以对此进行测试。我基本上已经提取并简化了Modernizr的检查方式:



 function is_touch_device4() {
    if ("ontouchstart" in window || window.TouchEvent)
        return true;

    if (window.DocumentTouch && document instanceof DocumentTouch)
        return true;

    const prefixes = ["", "-webkit-", "-moz-", "-o-", "-ms-"];
    const queries = prefixes.map(prefix => `(${prefix}touch-enabled)`);

    return window.matchMedia(queries.join(",")).matches;
}


console.log(is_touch_device4()); 




在这里,他们使用的是非标准的touch-enabled媒体查询功能,我认为这是一种奇怪且不明智的做法。但是,在现实世界中,我猜它是可行的。将来(当所有人都支持它们时),这些媒体查询功能可以为您提供相同的结果:pointerhover。说明了触摸检测的问题,请参阅:
Stu Cox:您无法检测到触摸屏。

评论


双爆炸将一个值强制转换为布尔值,强制该函数返回true或false。您可以在这里阅读有关它的更多信息:stackoverflow.com/questions/4686583/…

–Rob Flaherty
2012年4月28日14:00

这不适用于Opera Mobile 10或Internet Explorer Mobile 6(Windows Mobile 6.5)。

– doubleJ
2012年6月20日的19:00

双int(!!)是多余的,因为in运算符已经计算为布尔值。

–史蒂夫
2012年11月6日19:04

即使在非触摸设备(PC)中,“ onmsgesturechange”也评估为是。 window.navigator.msMaxTouchPoints似乎更准确。在这里找到它。

–史蒂夫
2012年11月20日在21:02

即使我的屏幕没有触摸传感器,在Windows 8的IE10上它的评估结果也正确。我将旧笔记本电脑从Windows 7升级到Windows 8。

– Pwner
2012年11月26日23:30

#3 楼

由于Modernizr在Windows Phone 8 / WinRT上未检测到IE10,因此一个简单的跨浏览器解决方案是:

var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;


您只需要检查一次设备即可不会突然支持或不支持触摸,因此只需将其存储在变量中即可更有效地使用它多次。

评论


窗口中的“ onmsgesturechange”还可以检测非触摸设备上的“桌面” IE10,因此这不是确定触摸的可靠方法。

–马特·斯托
13年1月20日在1:28

这个答案应该是可以接受的,因为它是最好,最简单且最新的答案。在一个函数中,我认为这会更加一致:return !!(窗口中的“ ontouchstart”)|| !!(window.navigator中的'msmaxtouchpoints'); (结合两个答案)在IE10中也能正常工作!

–叶提
13年4月9日在14:15

这应该是公认的答案。即使可以触摸,窗口中的“ onmsgesturechange”也将在IE10桌面上返回true

–山姆·桑顿
13年5月3日在16:51

您所需要的全部:函数isTouchDevice(){在窗口||中返回'ontouchstart' !!(navigator.msMaxTouchPoints);}

–GFoley83
2013年9月4日在6:20

甚至GFoley在窗口中建议“ ontouchstart” || !!(navigator.msMaxTouchPoints);在2014年2月Chrome 30开发者中返回的错误分数为正。

–汤姆·安德森(Tom Andersen)
2014年2月7日在17:39

#4 楼

由于引入了交互媒体功能,因此您可以轻松做到:

if(window.matchMedia("(pointer: coarse)").matches) {
    // touchscreen
}


https://www.w3.org/TR/mediaqueries-4/#descdef-media- any-pointer

更新(由于评论):上述解决方案是检测“粗指针”(通常是触摸屏)是否是主要输入设备。万一您想确定某个设备是否具有例如鼠标也有触摸屏,您可以改用any-pointer: coarse

有关更多信息,请参见此处:检测浏览器没有鼠标并且仅触摸

评论


这是迄今为止最好的解决方案,谢谢!尽管我建议使用(指针:粗糙的),因为您很可能只针对主要输入。由于少数不支持的浏览器仅是台式机,因此可以在生产中使用。在css-tricks上有一篇很棒的文章。

–法比安·冯·埃勒兹(Fabian von Ellerts)
19-4-9在9:17



这是我测试过的唯一可在每种情况下使用的解决方案。谢谢!

–kaiserkiwi
2月20日14:45

#5 楼

使用以上所有注释,我汇编了以下符合我需要的代码:

var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));


我已经在iPad,Android(浏览器和Chrome)上对此进行了测试, Blackberry Playbook,iPhone 4s,Windows Phone 8,IE 10,IE 8,IE 10(带有触摸屏的Windows 8),Opera,Chrome和Firefox。

它目前在Windows Phone 7上无法运行,我还没有尚未能够找到该浏览器的解决方案。

希望有人觉得这很有用。

评论


有什么原因不能使用:function is_touch_device(){return !!(窗口中的“ ontouchstart”)|| !!(导航器中的'msmaxtouchpoints'); };

–sidonaldson
13-4-24在9:55



使用该函数可以工作,但是我通常喜欢使用上面的变量方法,因此它仅需测试一次,并且稍后在代码中进行检查时会更快。另外,我发现我需要进行测试以查看msMaxTouchPoints是否大于0,因为Windows 8上的IE 10(不带触摸屏)返回0作为msMaxTouchPoints。

–大卫
13年4月29日在13:37



在Windows 7的Firefox 32上返回true :(

– vsync
2014-11-27 14:06

Windows 8上的Firefox 33和33.1在我的系统上均正确显示false。如果将Firefox升级到最新版本,它仍然返回true吗?您是否在计算机上安装了可能使Firefox错误地认为您的计算机具有触摸功能的设备?

–大卫
2014年11月27日15:17

>>>窗口中的'ontouchstart'>>> Ubuntu上为true FF 51.0.1

–拉维·加迪亚(Ravi Gadhia)
17 Mar 3 '17 at 10:06



#6 楼

我喜欢这个:

function isTouchDevice(){
    return typeof window.ontouchstart !== 'undefined';
}

alert(isTouchDevice());


评论


无需使用三元表达式返回布尔值。只需使用表达式即可返回布尔值。函数isTouchDevice(){return(window.ontouchstart!==未定义); }

– Tim Vermaelen
2013年6月13日15:08



您也可以只使用:window中的var isTouch ='ontouchstart';但是,这不适用于最新的Chrome(v31),window.document中的var isTouch ='createTouch';仍在工作。

–奥利维尔
2014年1月19日15:55

如先前接受的问题的评论中所述。 “ Modernizr不会测试触摸屏。它会测试浏览器中是否存在触摸事件”。从技术上来说,您的函数是hasTouchEvents()而不是isTouchDevice()

– hexalys
2014年2月1日在3:28



请注意,仅测试touchstart的类似方法将无法将Surface识别为触摸设备,因为IE而是使用了指针事件。

–CookieMonster
2014年3月18日在13:22

也许@Nis是正确的,但是在Firefox 39中,它正确返回了false。

– Dan Dascalescu
15年7月15日在1:25

#7 楼

如果您使用Modernizr,则如前所述使用Modernizr.touch非常容易。

但是,为了安全起见,我更喜欢结合使用Modernizr.touch和用户代理测试。

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

if (isTouchDevice) {
        //Do something touchy
    } else {
        //Can't touch this
    }


如果您不使用Modernizr,则只需将上面的Modernizr.touch函数替换为('ontouchstart' in document.documentElement)

,还要注意,测试用户代理iemobile可以为您提供更广泛的检测到Microsoft移动设备的数量超过Windows Phone

也请参阅此SO问题

评论


“做一些棘手的事情”和“做不到的事情”有很多奖励积分

–李·撒克逊人
15年12月22日在10:36

您需要多次检查同一台设备,并且在只能使用一个设备时执行多个Regexes。另外,您正在执行不区分大小写的正则表达式,但是字符串已经小写。

–凯撒索尔
16-10-19在9:39

这应该足够了:/(iphone | ipod | ipad | android | iemobile | blackberry | bada)/。test(window.navigator.userAgent.toLowerCase())

–凯撒索尔
16-10-19在9:40

有什么理由要小写或使匹配的字符不区分大小写? “ iOS”,“ Android”或“ IEMobile”什么时候使用其他大小写?

– Henrik N
17-10-24在6:06

#8 楼

我们尝试了modernizr实现,但是检测触摸事件不再是一致的(IE 10在Windows桌面上具有触摸事件,IE 11可以正常工作,因为已经删除了触摸事件并添加了指针api)。

因此,只要我们不知道用户使用哪种输入类型,我们便决定将网站优化为触摸式网站。这比任何其他解决方案都更可靠。

我们的研究表明,大多数桌面用户在单击之前都会将鼠标移到屏幕上,因此我们可以检测到他们并更改其行为,然后他们才能单击或悬停任何内容。

这是我们代码的简化版本:

var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
    isTouch = false;
    window.removeEventListener('mousemove', mouseMoveDetector);
});


评论


当今的计算机同时具有触摸和鼠标功能……您必须与众不同。绝对必须知道它是仅触摸屏,鼠标还是两者。 3个不同的州。

– vsync
2014年11月27日14:10

是的,您是对的,但这很难。最好的情况是,您的应用程序设计为可被任何输入控制器使用,并且不在乎用户是否拥有触摸屏,鼠标,键盘或全部。

–马丁·兰兹(Martin Lantzsch)
2014年11月27日在21:24



用户的行为比用户拥有哪种设备的真实信息更有价值。当您知道用户拥有鼠标,触摸屏和键盘时-那又如何呢?处理行为(移动,触摸移动,按下按键等)。用户可以在“运行时”更改输入类型,这是一个真正的难题,当您正在开发使用8到5而无需重新加载的真实应用程序时。

–马丁·兰兹(Martin Lantzsch)
2014年11月28日在21:22

+1实用上这是对我最好的答案。例如,我有数据网格。这些数据网格将显示一个用于触摸以进行编辑的“编辑图标”,或一个用于显示更多选项的上下文菜单。如果检测到鼠标移动,则删除图标(在网格上节省空间),用户可以双击或右键单击。

– prograhammer
2015年7月9日在15:51



触摸设备上的Chrome偶尔会触发鼠标移动

– pstanton
17年7月25日在10:37

#9 楼

比检查他们是否有触摸屏要好得多,它可以检查是否正在使用它,而且检查起来也更容易。

if (window.addEventListener) {
    var once = false;
    window.addEventListener('touchstart', function(){
        if (!once) {
            once = true;
            // Do what you need for touch-screens only
        }
    });
}


#10 楼

工作小提琴

我已经做到了;

function isTouchDevice(){
    return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}

if(isTouchDevice()===true) {
    alert('Touch Device'); //your logic for touch device
}
else {
    alert('Not a Touch Device'); //your logic for non touch device
}


#11 楼

即使在Windows Surface平板电脑中,这一功能也能正常工作!!!

function detectTouchSupport {
msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
touchSupport = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch &&     document instanceof DocumentTouch);
if(touchSupport) {
    $("html").addClass("ci_touch");
}
else {
    $("html").addClass("ci_no_touch");
}
}


#12 楼

我使用上面的代码来检测是否触摸,所以我的fancybox iframe会显示在台式计算机上而不是触摸上。我注意到,仅使用blmstr的代码时,适用于Android 4.0的Opera Mini仍在注册为非触摸设备。 (有人知道为什么吗?)

我最终使用了:

<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>


评论


您能否解释一下,为什么不对单个正则表达式/ iPhone | iPod | iPad | Android | BlackBerry /使用单个匹配调用?

–德米特里·科罗里奥夫(Dmitry Koroliov)
2014年4月11日在9:02

Opera Mini在Opera的服务器上而不是在设备本身上进行渲染,所以这种方式有点奇怪。

– bluesmoon
15年8月24日在15:52

#13 楼

尝试检测触摸的最大“陷阱”是在同时支持触摸和触控板/鼠标的混合设备上。即使您能够正确检测用户设备是否支持触摸,您真正需要做的就是检测用户当前使用的输入设备。这里有关于此挑战的详细记录以及可能的解决方案。

基本上,确定用户只是触摸屏幕还是使用鼠标/触控板的方法是在页面上注册touchstartmouseover事件:

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
})();


更多详细信息。

#14 楼

实际上,我研究了这个问题并考虑了所有情况。因为这也是我项目中的大问题。因此,我达到以下功能,它适用于所有设备上所有浏览器的所有版本:

const isTouchDevice = () => {
  const prefixes = ['', '-webkit-', '-moz-', '-o-', '-ms-', ''];
  const mq = query => window.matchMedia(query).matches;

  if (
    'ontouchstart' in window ||
    (window.DocumentTouch && document instanceof DocumentTouch)
  ) {
    return true;
  }
  return mq(['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''));
};


提示:毫无疑问,isTouchDevice仅返回boolean值。

评论


我认为您需要const IsTouchDevice =(()=> {...})();

–抢夺
9月16日15:48

@Rob,它是一个函数,它在开发人员上如何使用它。

– AmerllicA
9月16日下午16:42

#15 楼

看看这篇文章,它提供了一个非常不错的代码段,用于检测到触摸设备时执行的操作或在调用touchstart事件时应执行的操作:

$(function(){
  if(window.Touch) {
    touch_detect.auto_detected();
  } else {
    document.ontouchstart = touch_detect.surface;
  }
}); // End loaded jQuery
var touch_detect = {
  auto_detected: function(event){
    /* add everything you want to do onLoad here (eg. activating hover controls) */
    alert('this was auto detected');
    activateTouchArea();
  },
  surface: function(event){
    /* add everything you want to do ontouchstart here (eg. drag & drop) - you can fire this in both places */
    alert('this was detected by touching');
    activateTouchArea();
  }
}; // touch_detect
function activateTouchArea(){
  /* make sure our screen doesn't scroll when we move the "touchable area" */
  var element = document.getElementById('element_id');
  element.addEventListener("touchstart", touchStart, false);
}
function touchStart(event) {
  /* modularize preventing the default behavior so we can use it again */
  event.preventDefault();
}


#16 楼

我会避免使用屏幕宽度来确定设备是否为触摸设备。想想Windows 8,有比699px大得多的触摸屏。Navigatior.userAgent可能会很好地覆盖假阳性。

我建议您在Modernizr上检查此问题。

是否要测试设备是否支持触摸事件或是触摸设备。不幸的是,那不是同一回事。

#17 楼

不,不可能。给出的出色答案永远都是局部的,因为任何给定的方法都会产生误报和误报。由于OS API,即使浏览器也不总是知道是否存在触摸屏,并且在浏览器会话期间,尤其是使用KVM类型的布置时,事实可能会发生变化。

在此出色的工具中查看更多详细信息文章:

http://www.stucox.com/blog/you-cant-detect-a-touchscreen/

文章建议您重新考虑使您成为现实的假设想检测触摸屏,可能是错误的。 (我检查了自己的应用程序,但我的假设确实是错误的!)

本文的结论是:


对于布局,假定每个人都有触摸屏。鼠标用户可以使用大型UI控件,而触摸用户可以使用小型
控件。悬停状态也是如此。

对于事件和交互,假设任何人都可以拥有触摸屏。
相互实现键盘,鼠标和触摸交互,
确保彼此之间都不会阻塞其他。


#18 楼

这些工具很多,但要么需要jQuery,要么需要javascript linter抱怨语法。考虑到您的第一个问题需要一种“ JavaScript”(不是jQuery,不是Modernizr)的解决方案,这是一个每次都能使用的简单函数。


function isTouchDevice() {
    return !!window.ontouchstart;
}

console.log(isTouchDevice());


我要提到的最后一个好处是该代码与框架和设备无关。享受吧!

#19 楼

var isTouchScreen = 'createTouch' in document;




var isTouchScreen = 'createTouch' in document || screen.width <= 699 || 
    ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) || 
    ua.match(/Android/);


我想将是更彻底的检查。

评论


最好注意到ua指向navigator.userAgent。同样,如果有人在非全屏模式下打开浏览器,则按屏幕宽度进行的检测也会给出错误的结果。

–HoLyVieR
2011年11月5日,下午3:45

#20 楼

Chrome 24现在似乎支持触摸事件,可能适用于Windows8。因此此处发布的代码不再起作用。现在,我不再尝试检测浏览器是否支持触摸,而是绑定触摸和单击事件,并确保只调用了一个:

myCustomBind = function(controlName, callback) {

  $(controlName).bind('touchend click', function(e) {
    e.stopPropagation();
    e.preventDefault();

    callback.call();
  });
};


称呼它为

myCustomBind('#mnuRealtime', function () { ... });


希望有帮助!

评论


相关线程,stackoverflow.com / questions / 12566306 /…

–Air
2014年5月12日15:10

#21 楼

除适用于桌面的Firefox外,所有受支持的浏览器始终为TRUE,因为即使您不单击“触摸按钮”,Firefox的桌面也支持开发人员的响应式设计!

我希望Mozilla会在下一版本中修复此问题。

我正在使用Firefox 28桌面。

function isTouch()
{
    return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}


评论


它仍然是32.0版,他们还没有修复!疯。为什么这不能切换?这总是返回true :(

– vsync
2014年11月27日14:12



#22 楼

jQuery v1.11.3

提供的答案中有很多很好的信息。但是,最近,我花了很多时间尝试将所有内容实际结合到一个可行的解决方案中,以完成两件事:检测正在使用的设备是触摸屏类型的设备。
检测到设备被窃听。

除了这篇文章和使用Javascript检测触摸屏设备之外,我发现Patrick Lauke的这篇文章非常有帮助:https://hacks.mozilla.org/ 2013/04 /检测触摸为什么的方式/

这是代码...

$(document).ready(function() {
//The page is "ready" and the document can be manipulated.

    if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0))
    {
      //If the device is a touch capable device, then...
      $(document).on("touchstart", "a", function() {

        //Do something on tap.

      });
    }
    else
    {
      null;
    }
});


重要! *.on( events [, selector ] [, data ], handler )方法需要具有一个选择器,通常是一个元素,可以处理“ touchstart”事件或与触摸相关的任何其他事件。在这种情况下,它是超链接元素“ a”。

现在,您无需处理JavaScript中的常规鼠标单击操作,因为您可以使用CSS通过选择器的选择器来处理这些事件。超链接“ a”元素如下:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}


注意:还有其他选择器...

#23 楼

问题
由于混合使用触摸和鼠标输入的混合设备,您需要能够动态更改状态/变量,该状态/变量控制如果用户是触摸用户,是否应该运行一段代码。
触摸设备也会在点击时触发mousemove
解决方案
等待直到触发touchstart事件,然后将其设置为true。
如果触发touchstart,则添加一个mousemove处理程序。
如果两次mousemove事件触发之间的时间少于20ms,则假定它们使用鼠标作为输入。删除事件,因为它不再需要,并且mousemove对于鼠标设备来说是一个昂贵的事件。
再次触发touchstart(用户重新使用touch)后,该变量将设置为true。并重复此过程,以便以动态方式确定它。如果奇迹般快速地将mousemove触发两次触摸(在我的测试中,几乎不可能在20ms内触发),则下一次touchstart会将其设置为true。

在Safari iOS和Chrome上进行了测试适用于Android。
注意:不能100%确定MS Surface等的指针事件。
Codepen演示

const supportsTouch = 'ontouchstart' in window;
let isUsingTouch = false;

// `touchstart`, `pointerdown`
const touchHandler = () => {
  isUsingTouch = true;
  document.addEventListener('mousemove', mousemoveHandler);
};

// use a simple closure to store previous time as internal state
const mousemoveHandler = (() => {
  let time;
  
  return () => {
    const now = performance.now();

    if (now - time < 20) {
      isUsingTouch = false;
      document.removeEventListener('mousemove', mousemoveHandler);
    }

    time = now;
  }
})();

// add listeners
if (supportsTouch) {
  document.addEventListener('touchstart', touchHandler);
} else if (navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
  document.addEventListener('pointerdown', touchHandler);
}


#24 楼

我在jQuery mobile 1.0.1中使用:

if(jQuery.support.touch){
    alert('Touch enabled');
}



#25 楼

我还为如何在Javascript中检测页面是否在触摸屏设备上显示而在不同选项上作了很多努力。
IMO,到目前为止,尚不存在真正的选项来正确检测该选项。 >浏览器要么报告台式机上的触摸事件(因为操作系统可能支持触摸),要么某些解决方案不能在所有移动设备上运行。

最后,我意识到我一直在关注从一开始就使用错误的方法:
如果我的页面在触摸和非触摸设备上看起来很相似,那么我也许根本不必担心检测该属性:
我的情况是停用工具提示触摸设备上的按钮,因为它们会导致双击,因此我希望单击一下即可激活按钮。

我的解决方案是重构视图,以便在按钮上不需要工具提示,并且最后,我不需要使用所有都有缺点的方法从Javascript中检测触摸设备。

#26 楼

您可以安装现代化器并使用简单的触摸事件。这非常有效,并且可以在我测试过的所有设备(包括Windows表面)上使用!

我创建了jsFiddle

function isTouchDevice(){
    if(Modernizr.hasEvent('touchstart') || navigator.userAgent.search(/Touch/i) != -1){
         alert("is touch");
            return true;
         }else{
            alert("is not touch");
            return false;
    }
}


评论


欢迎来到SO!单独的代码(如未注释的代码)很少构成答案。您可以通过添加摘要说明来改善此答案。

– ebarr
2014年5月21日在10:02

#27 楼

实际的答案似乎是考虑上下文的​​答案:

1)公共站点(无登录)
对UI进行编码以将这两个选项一起使用。

2)登录站点
捕获是否在登录表单上发生了鼠标移动,并将其保存到隐藏的输入中。该值与登录凭据一起传递并添加到用户的会话中,因此可以在会话期间使用。

仅添加到登录页面的Jquery:

$('#istouch').val(1); // <-- value will be submitted with login form

if (window.addEventListener) {
    window.addEventListener('mousemove', function mouseMoveListener(){
        // Update hidden input value to false, and stop listening
        $('#istouch').val(0); 
        window.removeEventListener('mousemove', mouseMoveListener);
    });
} 


(+1回复@Dave Burt,+ 1回复@Martin Lantzsch)

#28 楼

没错,因此在检测触摸/非触摸设备方面存在巨大争议。窗口输入板的数量和输入板的大小正在增加,这给我们的Web开发人员带来了另一组头痛。
我已经使用并测试了blmstr的菜单答案。菜单的工作方式如下:当页面加载时,脚本将检测这是触摸设备还是非触摸设备。基于此菜单可以在悬停(非触摸)或单击/轻击(触摸)上运行。
在大多数情况下,blmstr的脚本似乎运行得很好(特别是2018年的脚本)。但是仍然有一个设备在不触摸时会被检测为触摸,反之亦然。
由于这个原因,我做了一些挖掘工作,并且由于本文的缘故,我将blmstr的第4个脚本中的几行替换为:



 function is_touch_device4() {
    if ("ontouchstart" in window)
        return true;

    if (window.DocumentTouch && document instanceof DocumentTouch)
        return true;


    return window.matchMedia( "(pointer: coarse)" ).matches;
}

alert('Is touch device: '+is_touch_device4());
console.log('Is touch device: '+is_touch_device4()); 




由于锁定设备的供应有限,因此无法对其进行测试,但是到目前为止,上述方法都非常有效。 )可以确认脚本是否可以正常工作。
现在就支持指针:似乎支持粗媒体查询。我在上面保留了这些行,因为在移动firefox上遇到了(由于某种原因)问题,但是媒体查询上方的行可以解决问题。
谢谢

#29 楼

我认为最好的方法是:
var isTouchDevice =
    (('ontouchstart' in window) ||
    (navigator.maxTouchPoints > 0) ||
    (navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
    /* Code for touch device /*
}else{
    /* Code for non touch device */
}


评论


navigator.MaxTouchPoints-> navigator.maxTouchPoints

–李在浩(Jaeho Lee)
11月11日19:29



#30 楼

扩展jQuery support对象:

jQuery.support.touch = 'ontouchend' in document;


现在您可以在任何地方检查它,就像这样: