使用JavaScript检测“触摸屏”设备的最佳方法是什么?
我已经编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种JavaScript方法可以检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它可以在iOS、Android等平台上运行,但我还想根据用户的设备是否有触摸屏来编写条件语句 这可能吗?更新2021 要查看旧答案,请查看历史记录。我决定从头开始,因为当我把历史记录保留在帖子里的时候,它已经失控了 我最初的回答是,使用与Modernizer相同的功能可能是个好主意,但这不再有效,因为他们删除了此PR上的touchevents测试:因为这是一个令人困惑的主题 话虽如此,这应该是检测浏览器是否具有触摸功能的一种相当不错的方法: 功能触控装置{ 在窗口中返回“ontouchstart”|| navigator.maxTouchPoints>0|| navigator.msmax接触点>0; } 但是对于比我更聪明的人写的更高级的用例,我建议阅读以下文章: 更新2021 要查看旧答案,请查看历史记录。我决定从头开始,因为当我把历史记录保留在帖子里的时候,它已经失控了 我最初的回答是,使用与Modernizer相同的功能可能是个好主意,但这不再有效,因为他们删除了此PR上的touchevents测试:因为这是一个令人困惑的主题 话虽如此,这应该是检测浏览器是否具有触摸功能的一种相当不错的方法: 功能触控装置{ 在窗口中返回“ontouchstart”|| navigator.maxTouchPoints>0|| navigator.msmax接触点>0; } 但是对于比我更聪明的人写的更高级的用例,我建议阅读以下文章: 更新:在将整个功能检测库拉入项目之前,请阅读下面的内容。检测实际触摸支持更为复杂,Modernizer仅涵盖基本用例 是一个伟大的,轻量级的方式来做任何网站上的各种功能检测 它只是为每个特性向html元素添加类 然后,您可以在CSS和JS中轻松地定位这些特性。例如:使用JavaScript检测“触摸屏”设备的最佳方法是什么?,javascript,jquery,touch,Javascript,Jquery,Touch,我已经编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种JavaScript方法可以检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它可以在iOS、Android等平台上运行,但我还想根据用户的设备是否有触摸屏来编写条件语句 这可能吗?更新2021 要查看旧答案,请查看历史记录。我决定从头开始,因为当我把历史记录保留在帖子里的时候,它已经失控了 我最初的回答是,使用与Modernizer相同的功能可能是个好主意,但这不再有效,因为他们删
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
和Javascript jQuery示例:
$('html.touch #popup').hide();
更新:在将整个功能检测库拉入项目之前,请阅读下面的内容。检测实际触摸支持更为复杂,Modernizer仅涵盖基本用例
是一个伟大的,轻量级的方式来做任何网站上的各种功能检测
它只是为每个特性向html元素添加类
然后,您可以在CSS和JS中轻松地定位这些特性。例如:
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
和Javascript jQuery示例:
$('html.touch #popup').hide();
或
我想这将是一次更彻底的检查
或
我想这将是一个更彻底的检查。检查一下,它提供了一个非常好的代码片段,用于在检测到触摸设备时执行什么操作,或者在调用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();
}
看看这个,它提供了一个非常好的代码片段,用于在检测到触摸设备时执行什么操作,或者在调用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();
}
我使用上面的代码片段来检测触摸是否正常,所以我的fancybox iframes会显示在桌面电脑上,而不是触摸屏上。我注意到Opera Mini for Android 4.0在单独使用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>
我使用上面的代码片段来检测触摸是否正常,所以我的fancybox iframes会显示在桌面电脑上,而不是触摸屏上。我注意到Opera Mini for Android 4.0在单独使用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>
我使用:
在jQuery mobile 1.0.1中,我使用:
if(jQuery.support.touch){
alert('Touch enabled');
}
在jQuery mobile 1.0.1中,我喜欢这个:
我喜欢这个:
由于Modernizr在Windows Phone 8/WinRT上未检测到IE10,一个简单的跨浏览器解决方案是:
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
您只需检查一次,因为设备不会突然支持或不支持触摸,所以只需将其存储在一个变量中,这样您就可以更高效地多次使用它。由于Modernizer在Windows Phone 8/WinRT上未检测到IE10,一个简单的跨浏览器解决方案是:
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
您只需检查一次,因为设备不会突然支持或不支持触摸,所以只需将其存储在变量中,这样您就可以更高效地多次使用它。我将避免使用屏幕宽度来确定设备是否为触摸设备。有比699px大得多的触摸屏,想想Windows8。Navigatior.userAgent可以很好地覆盖错误的帖子 我建议你去看看Modernizer 是
您想测试该设备是否支持触摸事件或是触摸设备。不幸的是,这不是一回事。我会避免使用屏幕宽度来确定设备是否为触摸设备。有比699px大得多的触摸屏,想想Windows8。Navigatior.userAgent可以很好地覆盖错误的帖子 我建议你去看看Modernizer
是否要测试该设备是否支持触摸事件或是触摸设备。不幸的是,这不是一回事。看起来Chrome 24现在支持触摸事件,可能是针对Windows 8。因此,这里发布的代码不再有效。我不再尝试检测浏览器是否支持触摸,而是绑定触摸和单击事件,并确保只调用一个:
myCustomBind = function(controlName, callback) {
$(controlName).bind('touchend click', function(e) {
e.stopPropagation();
e.preventDefault();
callback.call();
});
};
然后称之为:
myCustomBind('#mnuRealtime', function () { ... });
希望这有帮助 Chrome 24现在似乎支持触摸事件,可能是针对Windows 8。因此,这里发布的代码不再有效。我不再尝试检测浏览器是否支持触摸,而是绑定触摸和单击事件,并确保只调用一个:
myCustomBind = function(controlName, callback) {
$(controlName).bind('touchend click', function(e) {
e.stopPropagation();
e.preventDefault();
callback.call();
});
};
然后称之为:
myCustomBind('#mnuRealtime', function () { ... });
希望这有帮助 使用上面的所有注释,我汇编了以下代码,这些代码符合我的需要:
var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
我已经在iPad、Android浏览器和Chrome、黑莓Playbook、iPhone4S、WindowsPhone8、IE10、IE8、IE10Windows8以及触摸屏、Opera、Chrome和Firefox上进行了测试
它目前在WindowsPhone7上失败,我还没有找到一个解决方案
希望有人觉得这很有用。使用上面的所有注释,我已经汇编了以下代码,这些代码符合我的需要:
var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
我已经在iPad、Android浏览器和Chrome、黑莓Playbook、iPhone4S、WindowsPhone8、IE10、IE8、IE10Windows8以及触摸屏、Opera、Chrome和Firefox上进行了测试
它目前在WindowsPhone7上失败,我还没有找到一个解决方案
希望有人会觉得这很有用。如果您使用,如前所述,使用modernizer.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
}
如果不使用Modernizer,只需将上面的Modernizer.touch功能替换为document.documentElement中的“ontouchstart”
还请注意,测试用户代理iemobile将为您提供比Windows Phone更大范围的检测到的Microsoft移动设备
如前所述,使用Modernizer.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
}
如果不使用Modernizer,只需将上面的Modernizer.touch功能替换为document.documentElement中的“ontouchstart”
还请注意,测试用户代理iemobile将为您提供比Windows Phone更大范围的检测到的Microsoft移动设备
这一款即使在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");
}
}
这一款即使在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");
}
}
扩展jQuery支持对象:
现在,您可以在任何地方查看它,如下所示:
if( jQuery.support.touch )
// do touch stuff
扩展jQuery支持对象:
现在,您可以在任何地方查看它,如下所示:
if( jQuery.support.touch )
// do touch stuff
除Firefox for desktop外,所有受支持的浏览器始终为真,因为Firefox for desktop support为开发者提供响应性设计,即使您单击或不单击触摸按钮 我希望Mozilla能在下一个版本中解决这个问题 我正在使用Firefox28桌面
function isTouch()
{
return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
除Firefox for desktop外,所有受支持的浏览器始终为真,因为Firefox for desktop support为开发者提供响应性设计,即使您单击或不单击触摸按钮 我希望Mozilla能在下一个版本中解决这个问题 我正在使用Firefox28桌面
function isTouch()
{
return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
对于如何在Javascript中检测页面是否显示在触摸屏设备上,我还遇到了很多不同的选项。 国际海事组织(IMO)表示,截至目前,还不存在能够正确检测期权的实物期权。 浏览器要么报告桌面计算机上的触摸事件,因为操作系统可能已准备好触摸,要么某些解决方案无法在所有移动设备上运行 最后,我意识到我从一开始就采取了错误的方法: 如果我的页面在触摸和非触摸设备上看起来相似,我可能根本不必担心检测属性: 我的方案是在触摸设备上的按钮上禁用工具提示,因为它们会导致双击,而我希望一次点击就可以激活按钮
我的解决方案是重构视图,这样就不需要在按钮上显示工具提示,最终我不需要从Javascript中检测触摸设备,而这些方法都有其缺点。我还为如何在Javascript中检测页面是否显示在触摸屏设备上的不同选项而苦苦挣扎。 国际海事组织(IMO)表示,截至目前,还不存在能够正确检测期权的实物期权。 浏览器可以报告桌面计算机上的触摸事件 这是因为操作系统可能是触控就绪的,或者某些解决方案不能在所有移动设备上运行 最后,我意识到我从一开始就采取了错误的方法: 如果我的页面在触摸和非触摸设备上看起来相似,我可能根本不必担心检测属性: 我的方案是在触摸设备上的按钮上禁用工具提示,因为它们会导致双击,而我希望一次点击就可以激活按钮
我的解决方案是重构视图,这样就不需要在按钮上显示工具提示,最终我不需要从Javascript中检测触摸设备,这些方法都有缺点。您可以安装modernizer并使用简单的触摸事件。这是非常有效的,适用于我测试过的每一台设备,包括windows surface 我创造了一个
您可以安装modernizer并使用简单的触摸事件。这是非常有效的,适用于我测试过的每一台设备,包括windows surface 我创造了一个
我们尝试了Modernizer实现,但是检测触摸事件不再一致了IE 10在windows桌面上有触摸事件,IE 11可以工作,因为我们已经删除了触摸事件并添加了指针api 因此,我们决定优化网站作为一个触摸网站,只要我们不知道用户的输入类型。这比任何其他解决方案都更可靠 我们的研究表明,大多数桌面用户在点击前会将鼠标移到屏幕上,因此我们可以检测到他们并在他们能够点击或悬停任何东西之前改变他们的行为 这是我们代码的简化版本:
var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
isTouch = false;
window.removeEventListener('mousemove', mouseMoveDetector);
});
我们尝试了Modernizer实现,但是检测触摸事件不再一致了IE 10在windows桌面上有触摸事件,IE 11可以工作,因为我们已经删除了触摸事件并添加了指针api 因此,我们决定优化网站作为一个触摸网站,只要我们不知道用户的输入类型。这比任何其他解决方案都更可靠 我们的研究表明,大多数桌面用户在点击前会将鼠标移到屏幕上,因此我们可以检测到他们并在他们能够点击或悬停任何东西之前改变他们的行为 这是我们代码的简化版本:
var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
isTouch = false;
window.removeEventListener('mousemove', mouseMoveDetector);
});
我是这样做到的,
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
}
我是这样做到的,
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
}
其中许多都可以工作,但要么需要jQuery,要么javascript过滤器抱怨语法。考虑到您最初的问题要求使用JavaScript而不是jQuery,而不是Modernizer来解决这个问题,这里有一个简单的函数,每次都可以使用。这也是你能得到的最小值
function isTouchDevice() {
return !!window.ontouchstart;
}
console.log(isTouchDevice());
我要提到的最后一个好处是,这段代码与框架和设备无关。享受吧 其中许多都可以工作,但要么需要jQuery,要么javascript linter抱怨语法。考虑到您最初的问题要求使用JavaScript而不是jQuery,而不是Modernizer来解决这个问题,这里有一个简单的函数,每次都可以使用。这也是你能得到的最小值
function isTouchDevice() {
return !!window.ontouchstart;
}
console.log(isTouchDevice());
我要提到的最后一个好处是,这段代码与框架和设备无关。享受吧 不,这是不可能的。给出的优秀答案永远都是局部的,因为任何给定的方法都会产生误报和误报。由于操作系统API的原因,即使是浏览器也不总是知道触摸屏是否存在,而且在浏览器会话期间,这一事实可能会发生变化,特别是在KVM类型的安排下 请参阅这篇优秀文章中的更多详细信息: 这篇文章建议你重新考虑那些让你想要检测触摸屏的假设,它们可能是错误的。我检查了我自己的应用程序,我的假设确实是错误的 文章的结论是: 对于布局,假设每个人都有一个触摸屏。鼠标用户可以使用 大用户界面控制比触摸屏用户使用小用户界面要容易得多 一个。悬停状态也是如此 对于事件和交互,假设任何人都有触摸屏。 实现键盘、鼠标和触摸交互, 确保没有相互阻碍
不,不可能。给出的优秀答案永远都是局部的,因为任何给定的方法都会产生误报和误报。由于操作系统API的原因,即使是浏览器也不总是知道触摸屏是否存在,而且在浏览器会话期间,这一事实可能会发生变化,特别是在KVM类型的安排下 请参阅这篇优秀文章中的更多详细信息: 这篇文章建议你重新考虑那些让你想要检测触摸屏的假设,它们可能是错误的。我检查了我自己的应用程序,我的假设确实是错误的 文章的结论是: 对于布局,假设每个人都有一个触摸屏。鼠标用户可以使用 大用户界面控制比触摸屏用户使用小用户界面要容易得多 一个。悬停状态也是如此 对于事件和交互,假设任何人都有一个tou 屏幕。 实现键盘、鼠标和触摸交互, 确保没有相互阻碍
有比检查他们是否有触摸屏更好的方法,就是检查他们是否在使用触摸屏,而且更容易检查
if (window.addEventListener) {
var once = false;
window.addEventListener('touchstart', function(){
if (!once) {
once = true;
// Do what you need for touch-screens only
}
});
}
有比检查他们是否有触摸屏更好的方法,就是检查他们是否在使用触摸屏,而且更容易检查
if (window.addEventListener) {
var once = false;
window.addEventListener('touchstart', function(){
if (!once) {
once = true;
// Do what you need for touch-screens only
}
});
}
实际的答案似乎是一个考虑上下文的答案: 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的回答实际答案似乎是考虑了上下文: 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的回答jQuery v1.11.3
在提供的答案中有很多好的信息。但是,最近我花了很多时间试图将所有内容结合到一个可行的解决方案中,以实现两件事:
检测正在使用的设备是否为触摸屏型设备。
检测设备是否被窃听。
除了这篇文章,我发现帕特里克·劳克的这篇文章非常有用:
这是代码
$(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]处理程序方法需要有一个选择器,通常是一个元素,可以处理touchstart事件或与触摸相关的任何其他类似事件。在本例中,它是超链接元素a
现在,您不需要在JavaScript中处理常规的鼠标单击,因为您可以使用CSS来处理这些事件,使用超链接的选择器a元素如下:
/* unvisited link */
a:link
{
}
/* visited link */
a:visited
{
}
/* mouse over link */
a:hover
{
}
/* selected link */
a:active
{
}
注意:还有其他选择器…jqueryv1.11.3
在提供的答案中有很多好的信息。但是,最近我花了很多时间试图将所有内容结合到一个可行的解决方案中,以实现两件事:
检测正在使用的设备是否为触摸屏型设备。
检测设备是否被窃听。
除了这篇文章,我发现帕特里克·劳克的这篇文章非常有用:
这是代码
$(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]处理程序方法需要有一个选择器,通常是一个元素,可以处理touchstart事件或与触摸相关的任何其他类似事件。在本例中,它是超链接元素a
现在,您不需要在JavaScript中处理常规的鼠标单击,因为您可以使用CSS来处理这些事件,使用超链接的选择器a元素如下:
/* unvisited link */
a:link
{
}
/* visited link */
a:visited
{
}
/* mouse over link */
a:hover
{
}
/* selected link */
a:active
{
}
注意:还有其他选择器…尝试检测触摸的最大障碍是在同时支持触摸和触摸板/鼠标的混合设备上。即使您能够正确检测用户的设备是否支持触摸,您真正需要做的是检测用户当前使用的输入设备。有一篇关于这项挑战和挑战的详细报道 基本上,确定用户是只是触摸屏幕还是使用鼠标/触控板的方法是在页面上注册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
})();
更多细节。尝试检测触摸的最大难题是在支持触摸和触摸板/鼠标的混合设备上。即使您能够正确检测用户的设备是否支持触摸,您真正需要做的是检测用户当前使用的输入设备。有一篇关于这项挑战和挑战的详细报道 基本上,确定用户是只是触摸屏幕还是使用鼠标/触控板的方法是在页面上注册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类,以反映用户当前在文档上的输入类型
新界:
更多详细信息。问题
由于混合设备使用触摸和鼠标输入的组合,您需要能够动态更改状态/变量,该状态/变量控制用户是否为触摸用户时代码是否应运行
触摸设备还可以在点击时触发鼠标移动
解决方案
假设加载时触摸错误。
等待触发touchstart事件,然后将其设置为true。
如果触发了touchstart,请添加mousemove处理程序。
如果两个mousemove事件触发之间的时间小于20毫秒,则假定它们使用鼠标作为输入。删除该事件,因为它不再需要,而mousemove对于鼠标设备来说是一个昂贵的事件。
一旦再次启动touchstart,用户将返回使用touch,变量将被设置为true。然后重复这个过程,以动态方式确定。如果在我的测试中,mousemove在触摸屏上以荒谬的速度被触发两次,那么实际上不可能在20毫秒内触发,下一次touchstart会将其设置为true。
在Safari iOS和Android Chrome上测试
注意:MS Surface等的指针事件不能100%确定
问题
由于混合设备使用触摸和鼠标输入的组合,您需要能够动态更改状态/变量,该状态/变量控制用户是否为触摸用户时代码是否应运行
触摸设备还可以在点击时触发鼠标移动
解决方案
假设加载时触摸错误。
等待触发touchstart事件,然后将其设置为true。
如果触发了touchstart,请添加mousemove处理程序。
如果两个mousemove事件触发之间的时间小于20毫秒,则假定它们使用鼠标作为输入。删除该事件,因为它不再需要,而mousemove对于鼠标设备来说是一个昂贵的事件。
一旦再次启动touchstart,用户将返回使用touch,变量将被设置为true。然后重复这个过程,以动态方式确定。如果在我的测试中,mousemove在触摸屏上以荒谬的速度被触发两次,那么实际上不可能在20毫秒内触发,下一次touchstart会将其设置为true。
在Safari iOS和Android Chrome上测试
注意:MS Surface等的指针事件不能100%确定
由于引入了交互媒体功能,您只需执行以下操作:
if(window.matchMedia("(pointer: coarse)").matches) {
// touchscreen
}
由于评论而更新:上述解决方案是检测粗指针(通常是触摸屏)是否是主要输入设备。如果您想检测带有鼠标等的设备是否也有触摸屏,您可以使用任意指针:粗略
有关更多信息,请查看此处:由于引入了交互媒体功能,您只需执行以下操作:
if(window.matchMedia("(pointer: coarse)").matches) {
// touchscreen
}
由于评论而更新:上述解决方案是检测粗指针(通常是触摸屏)是否是主要输入设备。如果您想检测带有鼠标等的设备是否也有触摸屏,您可以使用任意指针:粗略
有关更多信息,请查看此处:我认为最好的方法是:
var isTouchDevice =
(('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
/* Code for touch device /*
}else{
/* Code for non touch device */
}
我认为最好的方法是:
var isTouchDevice =
(('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
/* Code for touch device /*
}else{
/* Code for non touch device */
}
实际上,我研究了这个问题并考虑了所有的情况。因为这也是我项目中的一个大问题。因此,我实现了以下功能,它适用于所有设备上所有浏览器的所有版本:
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(''));
};
提示:肯定地,IsthouChice只返回布尔值。
实际上,我研究了这个问题并考虑了所有的情况。因为这也是我项目中的一个大问题。因此,我实现了以下功能,它适用于所有设备上所有浏览器的所有版本:
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(''));
};
提示:当然,iStouch设备只返回布尔值。没错,因此在检测触摸/非触摸设备方面存在着巨大的争论。视窗平板电脑的数量和尺寸不断增加,这又给我们的网络开发者带来了一系列麻烦 我已经使用并测试了菜单。菜单是这样工作的:当页面加载时,脚本会检测这是触摸还是非触摸设备。基于此,菜单将在悬停非触摸或点击/点击触摸上工作 在大多数情况下,blmstr的脚本似乎运行良好,特别是2018年的脚本。但仍有一种设备在非触摸时会被检测为触摸,反之亦然 出于这个原因,我做了一些挖掘,并将blmstr第四个脚本中的几行替换为: 功能是触摸设备4{ 如果在窗口中启动 返回true; 如果window.DocumentTouch&&documentinstanceof DocumentTouch 返回true; return window.matchMedia指针:粗略。匹配; } 警报“Is触摸设备:”+Is触摸设备4;
控制台.log'Is touch device:'+Is_touch_device4 对,所以关于检测触摸/非触摸设备存在着巨大的争论。视窗平板电脑的数量和尺寸不断增加,这又给我们的网络开发者带来了一系列麻烦 我已经使用并测试了菜单。菜单的工作方式如下:当页面加载脚本时 检测这是触摸式还是非触摸式设备。基于此,菜单将在悬停非触摸或点击/点击触摸上工作 在大多数情况下,blmstr的脚本似乎运行良好,特别是2018年的脚本。但仍有一种设备在非触摸时会被检测为触摸,反之亦然 出于这个原因,我做了一些挖掘,并将blmstr第四个脚本中的几行替换为: 功能是触摸设备4{ 如果在窗口中启动 返回true; 如果window.DocumentTouch&&documentinstanceof DocumentTouch 返回true; return window.matchMedia指针:粗略。匹配; } 警报“Is触摸设备:”+Is触摸设备4;
控制台.log'Is touch device:'+Is_touch_device4;最好注意ua指的是navigator.userAgent。另外,如果有人在非全屏模式下打开浏览器,通过屏幕宽度进行检测可能会给出错误的结果。请注意,ua指的是navigator.userAgent。此外,如果有人在非全屏模式下打开浏览器,通过屏幕宽度进行检测可能会给出错误的结果。Modernizer不测试触摸屏。它测试浏览器中是否存在触摸事件。请参阅文档中的Misc Tests部分:如果modernizer.touch{/*do touch stuff/}或者{/fine,don*/}到@harrylove的观点,自Windows 8问世以来,modernizer一直错误地将我电脑的所有浏览器返回为触摸兼容。更新:blmstr的答案更好,并且是一个纯Javascript解决方案。如果Modernizr.touch意外返回未定义,您可能有一个定制的Modernizr,您可以在不支持触摸事件检测的情况下选择。Modernizr不测试触摸屏。它测试浏览器中是否存在触摸事件。请参阅文档中的Misc Tests部分:如果modernizer.touch{/*do touch stuff/}或者{/fine,don*/}到@harrylove的观点,自Windows 8问世以来,modernizer一直错误地将我电脑的所有浏览器返回为触摸兼容。更新:blmstr的答案更好,并且是一个纯Javascript解决方案。如果Modernizr.touch意外返回未定义,您可能会有一个定制的Modernizr,您可以在不支持触摸事件检测的情况下进行选择。双重爆炸将一个值转换为布尔值,迫使函数返回true或false。你可以在这里了解更多:这不适用于Opera Mobile 10或Internet Explorer Mobile 6 Windows Mobile 6.5。双倍不能!!是多余的,因为in运算符的计算结果已为布尔值。“OnMsgTestureChange”的计算结果为true,即使在非触摸设备PC中也是如此。window.navigator.msMaxTouchPoints似乎更准确。尽管我的屏幕上没有触摸传感器,但在Windows8上的IE10上它的评估结果是正确的。我将我的旧笔记本电脑从Windows7升级到Windows8。双重爆炸将一个值转换为布尔值,迫使函数返回true或false。你可以在这里了解更多:这不适用于Opera Mobile 10或Internet Explorer Mobile 6 Windows Mobile 6.5。双倍不能!!是多余的,因为in运算符的计算结果已为布尔值。“OnMsgTestureChange”的计算结果为true,即使在非触摸设备PC中也是如此。window.navigator.msMaxTouchPoints似乎更准确。尽管我的屏幕上没有触摸传感器,但在Windows8上的IE10上它的评估结果是正确的。我将我的旧笔记本电脑从Windows 7升级到Windows 8。Windows中的“OnMsgTestureChange”还检测非触摸设备上的桌面IE10,因此这不是确定触摸的可靠方法。这个答案应该被接受,因为它是最好、最简单和最新的。在函数中,我相信这会更加一致:return!!'ontouchstart'在窗口中| |window.navigator中的msmaxtouchpoints;在IE10中,将这两个答案结合起来也很好!这应该是公认的答案。”在IE10桌面上,即使触摸可能,窗口中的OnMsgTestureChange也会返回真值。您需要:函数isTouchDevice{return'ontouchstart'在窗口中| |!!navigator.msMaxTouchPoints;}甚至Gfoley建议在窗口中| | |!!navigator.msmax接触点;在Chrome 30 dev 2014年2月30日中返回fals阳性。窗口中的“OnMsgTestureChange”还检测非触摸设备上的桌面IE10,因此这不是确定触摸的可靠方法。这个答案应该被接受,因为它是最好、最简单和最新的答案。在函数中,我相信这会更加一致:return!!'ontouchstart'在窗口中| |window.navigator中的msmaxtouchpoints;在IE10中,将这两个答案结合起来也很好!这应该是公认的答案。”在IE10桌面上,即使触摸可能,窗口中的OnMsgTestureChange也会返回真值。您需要:函数isTouchDevice{return'ontouchstart'在窗口中| |!!navigator.msMaxTouchPoints;}甚至Gfoley建议在窗口中| | |!!navigator.msmax接触点;返回fal
Chrome 30 dev 2014年2月30日发布了一个正面消息。是否有任何原因使您不能使用:功能为_touch_device{return!!'ontouchstart'在窗口中| |!!!!'MSMAXStouchPoints'在navigator;};使用该函数会起作用,但我通常喜欢使用上面的变量方法,因此它只会被测试一次,并且在稍后的代码中检查时会更快。我还发现,我需要测试msMaxTouchPoints是否大于0,因为在没有触摸屏的Windows 8上,IE 10返回0作为msMaxTouchPoints。在Windows 7上的Firefox 32上返回true:在我的系统上,Firefox 33和Windows 8上的33.1都正确显示false。如果您将Firefox升级到最新版本,它是否仍然返回true?您的机器上是否安装了可能会使Firefox错误地认为您的机器具有触摸功能的设备?>>>>>窗口中的“ontouchstart”>>>UbuntUI上的true FF 51.0.1有任何原因您不能使用:函数是_touch_device{返回|窗口中的| | |!!导航器中的"msmaxtouchpoints};使用该函数会起作用,但我通常喜欢使用上面的变量方法,因此它只会被测试一次,并且在稍后的代码中检查时会更快。我还发现,我需要测试msMaxTouchPoints是否大于0,因为在没有触摸屏的Windows 8上,IE 10返回0作为msMaxTouchPoints。在Windows 7上的Firefox 32上返回true:在我的系统上,Firefox 33和Windows 8上的33.1都正确显示false。如果您将Firefox升级到最新版本,它是否仍然返回true?您的机器上是否安装了可能会使Firefox错误地认为您的机器具有触摸功能的设备?>>>>>窗口中的“ontouchstart”在ubuntuth上为true FF 51.0.1无需使用三元表达式返回布尔值。只需使用表达式返回布尔值。函数isTouchDevice{return window.ontouchstart!==undefined;}您也可以在window;}中使用:var isTouch='ontouchstart';,但是,这不适用于window.document中最新的Chromev31,var isTouch='createTouch';如先前接受的问题的评论中所述,仍在工作。Modernizer不测试触摸屏。它测试浏览器中是否存在触摸事件。从技术上讲,您的函数是hasTouchEvents而不是iTouchDeviceNote,即仅测试touchstart的类似方法将无法将Surface识别为触摸设备,因为IE使用指针事件。也许@Nis是正确的,但在Firefox 39中,它正确地返回false。不需要使用三元表达式来返回布尔值。只需使用表达式返回布尔值。函数isTouchDevice{return window.ontouchstart!==undefined;}您也可以在window;}中使用:var isTouch='ontouchstart';,但是,这不适用于window.document中最新的Chromev31,var isTouch='createTouch';如先前接受的问题的评论中所述,仍在工作。Modernizer不测试触摸屏。它测试浏览器中是否存在触摸事件。从技术上讲,您的函数是hasTouchEvents而不是iTouchDeviceNote,即仅测试touchstart的类似方法将无法将Surface识别为触摸设备,因为IE使用指针事件。也许@Nis是正确的,但在Firefox 39中,它正确地返回false。请您解释一下,为什么你不使用一个单一的匹配调用和一个单一的regexp/iPhone | iPod | iPad | Android | BlackBerry/?Opera Mini在Opera的服务器上而不是在设备本身上进行渲染,所以这种方式有点奇怪。你能解释一下吗,为什么你不使用一个单一的匹配调用和一个单一的regexp/iPhone | iPod | iPad | Android | BlackBerry/?Opera Mini在Opera的服务器上而不是在设备本身上进行渲染,所以这种方式有点奇怪。相关线程,相关线程,欢迎使用so!与未注释代码一样,代码本身很少构成答案。您可以通过添加对代码片段的解释来改进此答案。欢迎使用SO!与未注释代码一样,代码本身很少构成答案。您可以通过添加对代码片段的解释来改进此答案。今天的计算机既有触摸屏,也有鼠标……您必须加以区分。这是绝对必须知道,如果它只是触摸,鼠标,或两者兼而有之。3个不同的州。是的,你是对的,但这很难。在最好的情况下,您的应用程序被设计为可供任何输入控制器使用,而不关心用户是否拥有触摸屏、鼠标、键盘或所有设备。用户的行为比用户拥有何种设备的真实信息更有价值。当你知道用户有鼠标、触摸屏和键盘时——那又怎样?处理mousemove、touchmove、keydown等行为。用户可以在运行时更改其输入类型,这是一个真正的问题,当您开发一个实际应用程序时,它可以使用8到5次而无需重新加载。+1实用上,这是我的最佳答案。例如,我有爸爸
塔格里兹。这些数据网格将显示一个编辑图标以进行编辑,或显示一个上下文菜单以获取更多选项。如果检测到鼠标移动,则我会删除图标以节省网格上的空间,用户可以双击或右键单击。chrome on touch设备会触发鼠标移动有时今天的计算机既有触摸又有鼠标…您必须区分。这是绝对必须知道,如果它只是触摸,鼠标,或两者兼而有之。3个不同的州。是的,你是对的,但这很难。在最好的情况下,您的应用程序被设计为可供任何输入控制器使用,而不关心用户是否拥有触摸屏、鼠标、键盘或所有设备。用户的行为比用户拥有何种设备的真实信息更有价值。当你知道用户有鼠标、触摸屏和键盘时——那又怎样?处理mousemove、touchmove、keydown等行为。用户可以在运行时更改其输入类型,这是一个真正的问题,当您开发一个实际应用程序时,它可以使用8到5次而无需重新加载。+1实用上,这是我的最佳答案。例如,我有数据网格。这些数据网格将显示一个编辑图标以进行编辑,或显示一个上下文菜单以获取更多选项。如果检测到鼠标移动,则我会删除图标以节省网格上的空间,用户可以双击或右键单击。触摸设备上的chrome会偶尔触发mousemove。它仍然是32.0版,他们还没有修复它!精神失常的为什么这个不能切换??这总是返回真的:它仍然是32.0版,他们还没有修复它!精神失常的为什么这个不能切换??这总是正确的:如果你做了一些容易触碰的事情而不能触碰它,你会得到很多加分。你会对同一台设备进行多次检查,并在你可以只使用一台设备的情况下执行多个正则表达式。另外,您正在执行不区分大小写的正则表达式,但字符串已经是小写的。这应该足够了:/iphone | ipod | ipad | android | iemobile | blackberry | bada/.testwindow.navigator.userAgent.tolowercase有什么理由使用小写或使匹配的正则表达式不区分大小写?iOS、Android或IEMobile什么时候会使用其他外壳?做一些触感和不能触碰的事情会有很多加分。你在为同一台设备检查多次,并且在可以只使用一台的情况下执行多个正则表达式。另外,您正在执行不区分大小写的正则表达式,但字符串已经是小写的。这应该足够了:/iphone | ipod | ipad | android | iemobile | blackberry | bada/.testwindow.navigator.userAgent.tolowercase有什么理由使用小写或使匹配的正则表达式不区分大小写?iOS、Android或IEMobile何时会使用其他外壳?这是document.documentElement中var x='touchstart'的更好方式;console.logx//如果支持,则返回true//否则返回false如果新技术仍在出现,为什么该线程会受到保护?这是document.documentElement中var x='touchstart'的更好方法;console.logx//如果支持返回true//否则返回false如果新技术仍在出现,为什么该线程受到保护?这是迄今为止最好的解决方案,谢谢!尽管我建议使用pointer:rough,因为您很可能只针对主要输入。可以在生产中使用,因为少数不支持的浏览器仅限于桌面。关于这方面有一篇很棒的文章。这是我测试过的唯一一个在任何情况下都有效的解决方案。谢谢很好的答案,测试它,这是一个可靠的解决方案,谢谢分享…谢谢,太棒了,比任何其他解决方案都简单。这是迄今为止最好的解决方案,谢谢!尽管我建议使用pointer:rough,因为您很可能只针对主要输入。可以在生产中使用,因为少数不支持的浏览器仅限于桌面。关于这方面有一篇很棒的文章。这是我测试过的唯一一个在任何情况下都有效的解决方案。谢谢很好的答案,测试它,这是一个可靠的解决方案,谢谢分享…谢谢,太棒了,比任何其他解决方案都简单得多。我想你需要const-IsTouchDevice==>{…}@Rob,这是一个函数,如何使用它取决于开发人员@Rob,这是一个函数,由开发者决定如何使用它。navigator.MaxTouchPoints->navigator.MaxTouchPoints->navigator.MaxTouchPoints->navigator.MaxTouchPoints要捕获移动firefox,您可以将其添加到媒体查询中-moz touch enabled:1要捕获移动firefox,您可以将其添加到媒体查询中-moz touch已启用:1