デスクトップとモバイルの両方のデバイスで使用するためのjQueryプラグインを作成しました。デバイスにタッチスクリーン機能があるかどうかを検出する方法がJavaScriptにあるかどうか疑問に思いました。jquery-mobile.jsを使用してタッチスクリーンイベントを検出し、iOS、Androidなどで動作しますが、ユーザーのデバイスにタッチスクリーンがあるかどうかに基づいて条件ステートメントを記述したいと思います。
それは可能ですか?
デスクトップとモバイルの両方のデバイスで使用するための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.touch
予期せずが返された場合はundefined
、タッチイベント検出をサポートしていない、カスタマイズされたModernizr(選択して選択する)が存在する可能性があります。
この機能を使ってみましたか?(これは、Modernizrが使用していたものと同じです。)
function is_touch_device() {
try {
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
console.log(is_touch_device());
アップデート1
document.createEvent("TouchEvent")
true
最新のクローム(v。17)で戻ってきました。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());
アップデート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());
2018年の更新
時間が経つにつれ、これをテストする新しいより良い方法があります。基本的に、Modernizrによるチェック方法を抽出して簡略化しました。
function is_touch_device4() {
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);
}
console.log(is_touch_device4());
ここで彼らは非標準のtouch-enabled
メディアクエリ機能を使用していますが、これはちょっと奇妙で悪い習慣だと思います。しかし、ちょっと、現実の世界では、それはうまくいくと思います。(これらはすべてでサポートされています)将来的にはこれらのメディアクエリの機能はあなたに同じ結果を与えることができる:pointer
とhover
。
Modernizrがどのように実行しているかのソースを確認してください。
タッチ検出の問題を説明する優れた記事については、「Stu Cox:You Ca n't Detect a Touchscreen」を参照してください 。
true
またはを返すように強制しますfalse
。詳細については、こちらをご覧ください:stackoverflow.com/questions/4686583/…–
in
演算子はすでにブール値に評価されるため、二重のNOT(!!)は不必要です。
ModernizrはWindows Phone 8 / WinRTでIE10を検出しないため、シンプルなクロスブラウザーソリューションは次のとおりです。
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
デバイスが突然タッチをサポートしたりサポートしなくなったりすることはないため、一度チェックするだけでよいので、変数に格納するだけで複数回効率的に使用できます。
return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);
両方の答えを組み合わせるため)IE10でも正常に動作します!
'onmsgesturechange' in window
タッチが可能な場合でもIE10デスクトップでtrueを返す
function isTouchDevice() { return '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では失敗し、そのブラウザーの解決策をまだ見つけることができません。
誰かがこれが便利だと思うことを願っています。
true
Windows 7上の私のFirefox 32で戻ります:(
インタラクションメディア機能の導入により、次のことが簡単に行えます。
if(window.matchMedia("(pointer: coarse)").matches) {
// touchscreen
}
https://www.w3.org/TR/mediaqueries-4/#descdef-media-any-pointer
更新(コメントによる):上記の解決策は、「粗いポインター」(通常はタッチスクリーン)が主要な入力デバイスであるかどうかを検出することです。マウスなどのデバイスにタッチスクリーンがあるかどうかを判断したい場合は、any-pointer: coarse
代わりに。
詳細については、こちらをご覧ください:ブラウザーにマウスがなく、タッチのみであることの検出
(pointer: coarse)
ほとんどの場合、主要な入力のみを対象とするため、使用をお勧めします。サポートされていないブラウザはデスクトップのみであるため、本番環境で使用できます。css-tricksにこれに関する素晴らしい記事があります。
私はこれが好きです:
function isTouchDevice(){
return typeof window.ontouchstart !== 'undefined';
}
alert(isTouchDevice());
function isTouchDevice(){ return (window.ontouchstart !== undefined); }
var isTouch = 'ontouchstart' in window;
ただし、これは最新のChrome(v31)では機能せず、var isTouch = 'createTouch' in window.document;
まだ機能しています。
touchstart
IEがpointer
代わりにイベントを使用するため、同様のメソッドテストでは、Surfaceがタッチデバイスとして認識されないことに注意してください。
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
。
/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
私たちはmodernizrの実装を試しましたが、タッチイベントの検出は一貫していません(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
}
彼らがタッチスクリーンを持っているかどうかを確認するよりも良いことは、彼らがそれを使用しているかどうかを確認することです。さらに、より簡単に確認できます。
if (window.addEventListener) {
var once = false;
window.addEventListener('touchstart', function(){
if (!once) {
once = true;
// Do what you need for touch-screens only
}
});
}
これは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");
}
}
上記のコードを使用してタッチかどうかを検出したので、私のfancybox iframeはタッチではなくデスクトップコンピューターに表示されました。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>
/iPhone|iPod|iPad|Android|BlackBerry/
。
タッチを検出しようとする際の最大の問題は、タッチとトラックパッド/マウスの両方をサポートするハイブリッドデバイスです。ユーザーのデバイスがタッチをサポートしているかどうかを正しく検出できたとしても、本当に必要なのは、ユーザーが現在使用している入力デバイスを検出することです。この課題の詳細な説明と可能な解決策がここにあります。
基本的に、ユーザーが画面に触れただけなのか、それともマウス/トラックパッドを使用したのかを判断する方法は、ページに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イベントが呼び出された場合の処理について、非常に優れたコードスニペットが提供されています。
$(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();
}
いいえ、それは不可能です。与えられた優れた答えは部分的なものに過ぎません。なぜなら、与えられた方法はすべて、偽陽性と偽陰性を生み出すからです。OS APIのため、ブラウザーでさえタッチスクリーンが存在するかどうかを常に認識しているわけではなく、特にKVMタイプの配置では、ブラウザーセッション中に事実が変わる可能性があります。
この優れた記事で詳細をご覧ください。
http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
この記事では、タッチスクリーンを検出するための仮定を再考することをお勧めしていますが、それらはおそらく間違っています。(私は自分のアプリを自分で確認しましたが、私の仮定は確かに間違っていました!)
記事の結論は次のとおりです。
レイアウトについては、全員がタッチスクリーンを持っていると仮定します。マウスユーザーは、タッチユーザーが小さなUIコントロールを使用するよりもはるかに簡単に、大きなUIコントロールを使用できます。ホバー状態についても同様です。
イベントやインタラクションについては、誰もがタッチスクリーンを持っていると想定してください。キーボード、マウス、タッチ操作を並べて実装し、お互いを妨げないようにします。
これらの多くは機能しますが、jQueryを必要とするか、JavaScriptリンターが構文について文句を言います。あなたの最初の質問がこれを解決する「JavaScript」(jQueryではなく、Modernizrではない)方法を要求することを考えると、毎回機能する単純な関数は次のとおりです。それはまた、あなたが得ることができるのと同じくらい最小です。
function isTouchDevice() {
return !!window.ontouchstart;
}
console.log(isTouchDevice());
私が言及する最後の利点の1つは、このコードがフレームワークとデバイスに依存しないことです。楽しい!
function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}
これは私のために働いたので、Googleが私をここに連れてきたときにバニラJSスレッドも期待していたので、私はここでこの答えに貢献を追加しています。
Chrome 24はおそらくWindows 8向けのタッチイベントをサポートするようです。そのため、ここに投稿されたコードは機能しなくなりました。ブラウザでタッチがサポートされているかどうかを検出する代わりに、タッチイベントとクリックイベントの両方をバインドし、1つだけが呼び出されるようにします。
myCustomBind = function(controlName, callback) {
$(controlName).bind('touchend click', function(e) {
e.stopPropagation();
e.preventDefault();
callback.call();
});
};
そしてそれを呼び出す:
myCustomBind('#mnuRealtime', function () { ... });
お役に立てれば !
デスクトップ用Firefoxを除くすべてのブラウザーが常にTRUEに対応 Firefoxは、タッチボタンをクリックしてもしなくても、開発者向けのレスポンシブデザインをサポートしているため、です。
Mozillaが次のバージョンでこれを修正することを願っています。
Firefox 28デスクトップを使用しています。
function isTouch()
{
return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
true
:(
jQuery v1.11.3
提供された回答には多くの良い情報があります。しかし、最近、私は多くの時間を費やして、実際にすべてを1つにまとめて2つのことを達成するための実用的なソリューションにした。
この投稿とDetecting touch screen devices with Javascriptに加えて、Patrick Laukeによるこの投稿は非常に役に立ちました:https ://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /
ここにコードがあります...
$(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
{
}
注:他のセレクターもあります...
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
。また、誰かがフルスクリーンモードではないブラウザを開いた場合、画面幅による検出は誤った結果をもたらす可能性があります。
また、ページがタッチスクリーンデバイスに表示されているかどうかをJavascriptで検出する方法について、さまざまなオプションについても多く苦労しました。IMOには、現在のところ、オプションを適切に検出するための実際のオプションはありません。ブラウザは、デスクトップマシン上のタッチイベントを報告する(OSがタッチ対応の可能性があるため)か、一部のソリューションがすべてのモバイルデバイスで機能しない場合があります。
結局、最初から間違ったアプローチをとっていることに気づきました。タッチデバイスと非タッチデバイスでページの外観が似ている場合、プロパティの検出についてまったく心配する必要はないでしょう。私のシナリオはタッチデバイスのボタンをダブルタップするとボタンが1回タップされてボタンがアクティブになるので、ツールチップのボタンのツールチップを無効にします。
私の解決策は、ボタンの上にツールチップが必要ないようにビューをリファクタリングすることでした、そして結局、すべてに欠点があるメソッドを使ってJavaScriptからタッチデバイスを検出する必要がありませんでした。
あなたはmodernizerをインストールして、シンプルなタッチイベントを使うことができます。これは非常に効果的で、Windowsの表面を含め、テストしたすべてのデバイスで機能します。
function isTouchDevice(){
if(Modernizr.hasEvent('touchstart') || navigator.userAgent.search(/Touch/i) != -1){
alert("is touch");
return true;
}else{
alert("is not touch");
return false;
}
}
実用的な答えは、コンテキストを考慮したもののようです。
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);
});
}
(回答については、@ Dave Burtに+ 1、@ Martin Lantzschに+1)
タッチとマウス入力の組み合わせを使用するハイブリッドデバイスのため、動的に実行できる必要があります、ユーザーがタッチユーザーである場合にコードの一部を実行するかどうかを制御する状態/変数を変更。
タッチデバイスも発射します mousemove
タップでします。
touchstart
イベントが発生するまで待ち、それをtrueに設定します。Safari iOSとChrome for Androidでテストされています。
注: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);
}
実際、私はこの質問を調査し、すべての状況を検討しました。私のプロジェクトでも大きな問題です。だから私は以下の機能に到達します、それはすべてのデバイスのすべてのブラウザのすべてのバージョンで動作します:
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
値を返すだけです。
これは今のところ私にとってはうまく機能しているようです:
//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)
}
マウスが接続されている場合、ヒット率がかなり高い(実際には100%と言います)と、ページの準備ができた後、ユーザーがマウスを少なくともわずかな距離だけ移動したと想定できます。以下のメカニズムがこれを検出します。検出された場合、私はこれをタッチサポートの欠如の兆候と見なします。サポートされている場合は、マウスの使用中にそれほど重要ではないものと見なします。検出されない場合、タッチデバイスが想定されます。
編集このアプローチは、すべての目的に適合するとは限りません。これは、ロードされたページ、たとえば画像ビューアーでのユーザー操作に基づいてアクティブ化される機能を制御するために使用できます。以下のコードは、現在目立っているように、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;
}));