デスクトップとモバイルデバイスの両方で使用するためのjQueryプラグインを書きました。私は、デバイスにタッチスクリーン機能があるかどうかを検出するJavaScriptの方法があるのだろうかと思いました。私はjquery-mobile.jsを使ってタッチスクリーンのイベントを検出し、それはiOS、Androidなどで動作しますが、ユーザーのデバイスがタッチスクリーンを持っているかどうかに基づいて条件文を書きたいと思います。
それは可能ですか?
更新:機能検出ライブラリ全体をプロジェクトに取り込む前に、 blmstrの答え を読んでください。実際のタッチサポートを検出することはより複雑です、そしてModernizrは基本的なユースケースだけをカバーします。
Modernizr はあらゆるサイトであらゆる種類の機能検出を行うための優れた軽量な方法です。
各機能のhtml要素にクラスを追加するだけです。
そうすれば、CSSやJSでこれらの機能を簡単にターゲットにすることができます。例えば:
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
そしてJavascript(jQueryの例):
$('html.touch #popup').hide();
この機能を使ってみましたか? (これは、Modernizrが使用していたものと同じです。)
function is_touch_device() {
try {
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
UPDATE 1
document.createEvent("TouchEvent")
は最新のクロムでtrue
を返し始めました(v。17)。 Modernizrが少し前にこれを更新しました。 Modernizrのテストをここでチェックしてください 。
これを機能させるには、このように関数を更新します。
function is_touch_device() {
return 'ontouchstart' in window;
}
UPDATE 2
私は上記がIE10で働いていなかったことを発見しました(MS Surfaceでfalseを返す)。これが修正方法です。
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| 'onmsgesturechange' in window; // works on IE10 with some false positives
};
更新3
IEデスクトップのバージョンによっては'onmsgesturechange' in window
がtrueを返すので信頼できません。これはもう少し確実に機能します。
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| navigator.maxTouchPoints; // works on IE10/11 and Surface
};
UPDATE 2018
時が経ち、これをテストするための新しくてより良い方法があります。私は基本的にModernizrのそれをチェックする方法を抽出して単純化しました:
function is_touch_device() {
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var mq = function(query) {
return window.matchMedia(query).matches;
}
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
return mq(query);
}
ここで彼らは非標準のtouch-enabled
メディアクエリ機能を使用しています。これはちょっと変で悪い方法だと思います。しかし、実世界ではうまくいくと思います。将来的には(それらがすべてによってサポートされるとき)、それらのメディアクエリ機能はあなたに同じ結果を与えるかもしれません:pointer
とhover
。
Modernizrがそれを行っている方法の ソースをチェックしてください 。
タッチ検出に関する問題を説明した優れた記事については、 Stu Cox:タッチスクリーンを検出できない を参照してください。
ModernizrはWindows Phone 8/WinRTでIE10を検出しないので、単純なクロスブラウザソリューションは次のとおりです。
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
デバイスが突然タッチをサポートしていないかサポートしていないため、一度だけチェックする必要があるので、それを変数に格納するだけでより効率的に複数回使用できます。
上記のすべてのコメントを使用して、私は自分のニーズに合った次のコードをまとめました。
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 isTouchDevice(){
return typeof window.ontouchstart !== 'undefined';
}
alert(isTouchDevice());
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
というユーザーエージェントをテストすると、Windows Phone
よりも広範囲のMicrosoftモバイルデバイスが検出されることになります。
Modernizrの実装を試みましたが、タッチイベントの検出はもはや一貫していません(IE 10はWindowsデスクトップ上でタッチイベントを持っています、IE 11が機能します。
そのため、ユーザーがどの入力タイプを持っているかわからない限り、Webサイトをタッチサイトとして最適化することにしました。これは他のどのソリューションよりも信頼性があります。
私たちの研究によると、ほとんどのデスクトップユーザーはクリックする前にマウスで画面上を移動するので、クリックしたり何かを動かしたりする前にそれらを検出して動作を変更することができます。
これは私たちのコードを単純化したものです。
var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
isTouch = false;
window.removeEventListener('mousemove', mouseMoveDetector);
});
彼らがtouchScreenを持っているかどうかをチェックするより良い何かがあります、彼らがそれを使っているかどうかをチェックすることです、そしてそれはチェックするのがより簡単です。
if (window.addEventListener) {
var once = false;
window.addEventListener('touchstart', function(){
if (!once) {
once = true;
// Do what you need for touch-screens only
}
});
}
私はこれを達成しました。
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
}
これは、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");
}
}
インタラクションメディア機能の導入以来、あなたは単にすることができます:
if(window.matchMedia("(any-pointer: coarse)").matches) {
// touchscreen
}
https://www.w3.org/TR/mediaqueries-4/#descdef-media-any-pointer
タッチを検出しようとする際の最大の「落とし穴」は、タッチとトラックパッド/マウスの両方をサポートするハイブリッドデバイスです。ユーザーのデバイスがタッチをサポートしているかどうかを正しく検出できたとしても、本当に必要なのは、ユーザーが現在使用している入力デバイスを検出することです。この課題と ここでの可能な解決策 の詳細な説明があります。
基本的に、ユーザーが画面に触れただけか、マウス/トラックパッドを使用したかどうかを判断する方法は、ページで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
クラスを動的に追加または削除して、この時点でユーザーのcurrent入力タイプを反映するメカニズムを作成できます。ドキュメント:
;(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
})();
詳細 こちら 。
私はタッチかどうかを検出するために上記のコードの一部を使用したので、私のfancybox iframeはタッチではなくデスクトップコンピュータに表示されます。 blmstrのコードを単独で使用した場合、Opera Mini for Android 4.0はまだ非タッチデバイスとして登録されていました。 (誰もがその理由を知っていますか?)
私は使用してしまいました:
<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>
デバイスがタッチデバイスかどうかを判断するために画面幅を使用することは避けます。 699pxよりもはるかに大きいタッチスクリーンがあります。Windows8を考えてください。
この問題 / Modernizrでチェックアウトすることをお勧めします。
デバイスがタッチイベントをサポートしているのか、それともタッチデバイスであるのかをテストしますか。残念ながら、それは同じことではありません。
いいえ、できません。与えられた優れた答えは、決して部分的なものに過ぎません。与えられた方法では、偽陽性と偽陰性が生じるからです。 OS APIのせいで、ブラウザでさえタッチスクリーンが存在するかどうかを常に知るわけではなく、事実はブラウザセッション中に、特にKVMタイプの配置では変わる可能性があります。
この素晴らしい記事の詳細を参照してください。
http://www.stucox.com/blog/you-cant-detect-a-touchscreen/ /
この記事は、あなたがあなたがあなたがタッチスクリーンを検出したいという仮定を再考することを提案します、それらはおそらく間違っています。 (私は自分のアプリを自分でチェックしましたが、私の仮定は本当に間違っていました!)
この記事の結論は次のとおりです。
レイアウトについては、誰もがタッチスクリーンを持っていると仮定します。マウスユーザーは、タッチユーザーが小さなUIコントロールを使用するよりもはるかに簡単に大きなUIコントロールを使用できます。ホバー状態についても同じことが言えます。
イベントや交流のために、誰もがタッチスクリーンを持っていると仮定します。キーボード、マウス、およびタッチ操作を互いに並行して実装し、お互いがブロックされないようにします。
この post をチェックしてください。これは、タッチデバイスが検出されたときに何をすべきか、または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();
}
これらの作業の多くは、jQueryを必要とするか、JavaScriptリンターが構文に不満を持っています。あなたの最初の質問がこれを解決するための "JavaScript"(jQueryではなく、Modernizrではない)の方法を尋ねると考えると、これは毎回うまくいく簡単な関数です。それはまたあなたが得ることができるのと同じくらい最小限です。
function isTouchDevice() {
return !!window.ontouchstart;
}
console.log(isTouchDevice());
私が言及する最後の利点の1つは、このコードがフレームワークとデバイスに依存しないことです。楽しい!
Chrome 24は、おそらくWindows 8のタッチイベントをサポートしているようです。したがって、ここに投稿されたコードは機能しません。ブラウザでタッチがサポートされているかどうかを検出するのではなく、タッチイベントとクリックイベントの両方をバインドし、どちらか一方だけが呼び出されるようにします。
myCustomBind = function(controlName, callback) {
$(controlName).bind('touchend click', function(e) {
e.stopPropagation();
e.preventDefault();
callback.call();
});
};
そしてそれを呼び出します:
myCustomBind('#mnuRealtime', function () { ... });
お役に立てれば !
Modernizerをインストールして、単純なタッチイベントを使用することができます。これは非常に効果的であり、私がそれをテストしたすべてのデバイスで有効になります。
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;
}
}
jQuery v1.11.3
提供された回答にはたくさんの良い情報があります。しかし、最近、私は多くの時間を費やして、実際にすべてを結び付けて、2つのことを達成するための実用的なソリューションにまとめました。
この記事の他に、 - JavaScriptでタッチスクリーンデバイスを検出しています 、Patrick Laukeによるこの投稿は非常に役に立ちました。 https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why - ノット - ハウ - /
これがコードです...
$(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
{
}
注:他のセレクタもあります...
私はまた、Javascriptでページがタッチスクリーンデバイスに表示されているかどうかを検出する方法について、さまざまなオプションで苦労しました。 IMOは、現時点では、オプションを正しく検出するための実際のオプションはありません。ブラウザはデスクトップマシン上のタッチイベントを報告するか(OSはタッチ対応なので)、または一部のソリューションはすべてのモバイルデバイスで機能するわけではありません。
最終的に、私は最初から間違ったアプローチに従っていたことに気付きました。もし私のページがタッチと非タッチデバイスで似ているように見えるなら、私は多分財産を見つけることについて心配する必要はないはずです。タッチデバイス上のボタンの上にあるツールチップを非アクティブ化するには、それらがダブルタップになるので、シングルタップでボタンをアクティブにしたかったのです。
私の解決策は リファクタリング ボタンの上にツールチップが必要とされないようなビュー、そして結局私はJavascriptからタッチデバイスを検出する必要はない すべて欠点がある 。
デスクトップ用Firefoxを除くすべてのブラウザが常にサポートされています _ true _ デスクトップ用Firefoxは開発者向けのレスポンシブデザインであるため、タッチボタンをクリックしてもしなくても構いません。
Mozillaが次のバージョンでこれを修正することを願っています。
Firefox 28デスクトップを使用しています。
function isTouch()
{
return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
私が使う:
if(jQuery.support.touch){
alert('Touch enabled');
}
jQuery mobile 1.0.1では
タッチ入力とマウス入力の組み合わせを使用するハイブリッドデバイスのため、動的に動的に変更する必要があります。ユーザーがタッチユーザーであるかどうかにかかわらず実行する必要があります。
タッチデバイスは、タップ時にmousemove
も起動します。
touchstart
イベントが発生するまで待ってから、trueに設定します。Safari iOSおよびAndroidのChromeでテスト済み。
注:MS Surfaceなどのポインターイベントについては、100%確実ではありません。
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);
}
実用的な答えは、コンテキストを考慮したもののようです。
1)公開サイトログインなし)
両方のオプションを一緒に使用するようにUIをコーディングします。
2)ログインサイト
ログインフォーム上でマウスが動いたかどうかをキャプチャし、これを隠し入力に保存します。値はログイン認証情報とともに渡され、ユーザーのsessionに追加されるため、セッションの間使用できます。
ログインページのみに追加する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への回答)
var isTouchScreen = 'createTouch' in document;
または
var isTouchScreen = 'createTouch' in document || screen.width <= 699 ||
ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) ||
ua.match(/Android/);
もっと徹底的なチェックになると思います。
次のコードを使うことができます。
function isTouchDevice() {
var el = document.createElement('div');
el.setAttribute('ongesturestart', 'return;'); // or try "ontouchstart"
return typeof el.ongesturestart === "function";
}
出典: タッチベースの閲覧の検出 および @mplungjan post 。
上記の解決策は ブラウザスニッフィングなしのイベントサポートの検出 articleに基づいていました。
次の テストページ で結果を確認できます。
上記のコードはブラウザがタッチをサポートしているかどうかだけをテストし、デバイスはテストしていないことに注意してください。そのため、タッチスクリーン搭載のラップトップを使用している場合は、お使いのブラウザがタッチイベントをサポートしていない可能性があります。 最近のChromeはタッチイベントをサポートしています しかし、他のブラウザではサポートされていない可能性があります。
あなたも試すことができます:
if (document.documentElement.ontouchmove) {
// ...
}
しかし、iPhoneデバイスでは動作しないかもしれません。
$.support.touch ? "true" : "false";
これは今のところ私にとってはうまくいっているようです。
//Checks if a touch screen
is_touch_screen = 'ontouchstart' in document.documentElement;
if (is_touch_screen) {
// Do something if a touch screen
}
else {
// Not a touch screen (i.e. desktop)
}
undefined
はJavaScriptのキーワードではないため、window.ontouchstart !== undefined
を書くことになりがちな人へのクイックノート - > micnic answerを使用してください。 Developが次のように書くと大きな問題
undefined = window.ontouchstart;
開発者は彼らが望む未定義のものを作ることができます、そしてあなたはwindow.ontouchstart = myNonExistingWord;
かどうかをチェックすることもできます
この答えを出した人たちを失望させないでください。私もそれをコードに書いていることを確認してください。
var isTouchDevice =
(('ontouchstart' in window) ||
(navigator.MaxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
if(!isTouchDevice){
/* Code for touch device /*
}else{
/* Code for non touch device */
}
楽しむ !
エクステントjQueryのsupport
オブジェクト:
jQuery.support.touch = 'ontouchend' in document;
そして今、あなたはこのようにどこでもそれをチェックすることができます:
if( jQuery.support.touch )
// do touch stuff
マウスが接続されている場合、ページの準備ができた後、クリックなしでユーザーがマウスを少なくともわずかな距離だけ移動させるとかなり高いヒット率(私は100%と言うでしょう)で想定できます。以下のメカニズムがこれを検知します。検出された場合、私はこれがタッチサポートの欠如の兆候、またはサポートされている場合はマウスが使用されているときにはあまり重要ではないと見なします。検出されない場合はタッチデバイスと見なされます。
_ edit _ この方法はすべての目的に適しているとは限りません。ロードされたページでのユーザーの操作、たとえば画像ビューアに基づいてアクティブにされる機能を制御するために使用できます。以下のコードでは、mousemoveイベントも目立つようにマウスのないデバイスにバインドされたままになります。他のアプローチがより良いかもしれません。
おおまかに言って、これは次のようになります(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;
}));