Cách tốt nhất để phát hiện thiết bị 'màn hình cảm ứng' bằng JavaScript là gì?


416

Tôi đã viết một trình cắm jQuery để sử dụng trên cả máy tính để bàn và thiết bị di động. Tôi tự hỏi liệu có cách nào để JavaScript phát hiện xem thiết bị có khả năng màn hình cảm ứng không. Tôi đang sử dụng jquery-mobile.js để phát hiện các sự kiện trên màn hình cảm ứng và nó hoạt động trên iOS, Android, v.v., nhưng tôi cũng muốn viết các tuyên bố có điều kiện dựa trên việc thiết bị của người dùng có màn hình cảm ứng hay không.

Điều đó có thể không?


đây là cách tốt hơn var x = 'touchstart' trong document.documentEuity; console.log (x) // return true nếu được hỗ trợ //
other

Tại sao chủ đề này được bảo vệ nếu các kỹ thuật mới vẫn đang nổi lên?
Andy Hoffman

Câu trả lời:


139

Cập nhật: Vui lòng đọc câu trả lời của blmstr bên dưới trước khi kéo toàn bộ thư viện phát hiện tính năng vào dự án của bạn. Phát hiện hỗ trợ cảm ứng thực tế phức tạp hơn và Modernizr chỉ bao gồm một trường hợp sử dụng cơ bản.

Modernizr là một cách tuyệt vời, nhẹ để thực hiện tất cả các loại phát hiện tính năng trên bất kỳ trang web nào.

Nó chỉ đơn giản là thêm các lớp vào phần tử html cho mỗi tính năng.

Sau đó, bạn có thể nhắm mục tiêu các tính năng đó một cách dễ dàng trong CSS và JS. Ví dụ:

html.touch div {
    width: 480px;
}

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

Và Javascript (ví dụ về jQuery):

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

88
Modernizr không kiểm tra màn hình cảm ứng. Nó kiểm tra sự tồn tại của các sự kiện chạm trong trình duyệt. Xem phần "Thử nghiệm linh tinh" trong các tài liệu: Modernizr.com/docs/#features-misc
Harry Love

1
bạn cũng có thể thực hiện kiểm tra JS về sự tồn tại của các sự kiện chạm nếu (Modernizr.touch) {/ * làm công cụ cảm ứng /} khác {/ fine, không * /}
Anatoly G

7
Theo quan điểm của @ harrylove, kể từ khi Windows 8 ra mắt, Modernizr đã trả lại không chính xác tất cả các trình duyệt trên PC của tôi dưới dạng tương thích với cảm ứng.
Anton

3
Cập nhật: câu trả lời của blmstr là tốt hơn và là một giải pháp Javascript thuần túy.
Alan Christopher Thomas

1
Nếu Modernizr.touchbất ngờ quay lại undefined, bạn có thể có Modernizr tùy chỉnh (bạn có thể chọn và chọn) mà không cần hỗ trợ phát hiện Touch Event.
Henrik N

679

Bạn đã thử sử dụng chức năng này? (Điều này giống như Modernizr đã từng sử dụng.)

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

console.log(is_touch_device());

CẬP NHẬT 1

document.createEvent("TouchEvent")đã bắt đầu trở lại truetrong chrome mới nhất (câu 17). Modernizr cập nhật điều này một thời gian trước. Kiểm tra Modernizr kiểm tra ra ở đây .

Cập nhật chức năng của bạn như thế này để làm cho nó hoạt động:

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

console.log(is_touch_device1());

CẬP NHẬT 2

Tôi thấy rằng những thứ trên không hoạt động trên IE10 (trả về false trên MS Surface). Đây là cách khắc phục:

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

CẬP NHẬT 3

'onmsgesturechange' in windowsẽ trả về true trong một số phiên bản IE dành cho máy tính để bàn không đáng tin cậy. Điều này hoạt động đáng tin cậy hơn một chút:

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

CẬP NHẬT 2018

Thời gian trôi qua và có những cách mới và tốt hơn để kiểm tra điều này. Về cơ bản tôi đã trích xuất và đơn giản hóa cách kiểm tra của 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());

Ở đây họ đang sử dụng touch-enabledtính năng truy vấn phương tiện không chuẩn , mà tôi nghĩ là hơi lạ và thực hành xấu. Nhưng này, trong thế giới thực, tôi đoán nó hoạt động. Trong tương lai (khi tất cả chúng được hỗ trợ), các tính năng truy vấn phương tiện đó có thể cho bạn kết quả tương tự: pointerhover.

Kiểm tra nguồn gốc của Modernizr đang làm điều đó .

Để biết một bài viết hay giải thích các vấn đề với phát hiện cảm ứng, hãy xem: Stu Cox: Bạn không thể phát hiện màn hình cảm ứng .


20
Double bang tạo ra một giá trị cho boolean, buộc hàm phải trả về truehoặc false. Bạn có thể đọc thêm về nó ở đây: stackoverflow.com/questions/4686583/ cấp
Rob Flaherty

2
Điều này không hoạt động với Opera Mobile 10 hoặc Internet Explorer Mobile 6 (Windows Mobile 6.5).
doubleJ

17
Nhân đôi KHÔNG (!!) là không cần thiết vì intoán tử đã ước lượng thành boolean.
Steve

11
'onmsgesturechange'đang đánh giá đúng ngay cả trong các thiết bị không cảm ứng (PC). window.navigator.msMaxTouchPointsdường như chính xác hơn Tìm thấy nó ở đây .
Steve

6
Nó được đánh giá là đúng trên IE10 trên Windows 8 mặc dù màn hình của tôi không có cảm biến cảm ứng. Tôi đã nâng cấp máy tính xách tay cũ của mình từ Windows 7 lên Windows 8.
Pwner

120

Vì Modernizr không phát hiện IE10 trên Windows Phone 8 / WinRT, một giải pháp đa trình duyệt đơn giản là:

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

Bạn chỉ cần kiểm tra một lần vì thiết bị sẽ không hỗ trợ đột ngột hoặc không hỗ trợ cảm ứng, vì vậy chỉ cần lưu trữ thiết bị trong một biến để bạn có thể sử dụng thiết bị hiệu quả hơn nhiều lần.


3
'onmsgesturechange' trong cửa sổ cũng phát hiện IE10 "máy tính để bàn" trên các thiết bị không cảm ứng, vì vậy đây không phải là phương pháp xác định cảm ứng đáng tin cậy.
Matt Stow

6
Câu trả lời này nên được chấp nhận, vì nó là tốt nhất và đơn giản nhất và cập nhật nhất. Trong một chức năng tôi tin rằng điều này sẽ phù hợp hơn: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(để kết hợp cả hai câu trả lời) Cũng hoạt động tốt trong IE10!
Yeti

Đây phải là câu trả lời được chấp nhận. 'onmsgesturechange' in windowtrả về đúng trên máy tính để bàn IE10 ngay cả khi có thể chạm
Sam Thornton

6
Tất cả những gì bạn cần:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83

1
Ngay cả gợi ý 'ontouchstart' trong cửa sổ của GFoleys || !! (hoa tiêu.msMaxTouchPoints); trả về giá trị dương trong Chrome 30 dev tháng 2 năm 2014.
Tom Andersen

37

Sử dụng tất cả các ý kiến ​​trên Tôi đã tập hợp mã sau đây hoạt động cho nhu cầu của mình:

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

Tôi đã thử nghiệm điều này trên iPad, Android (Trình duyệt và Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 với Màn hình cảm ứng), Opera, Chrome và Firefox.

Hiện tại nó không thành công trên Windows Phone 7 và tôi chưa thể tìm ra giải pháp cho trình duyệt đó.

Hy vọng ai đó thấy điều này hữu ích.


Có bất kỳ lý do nào bạn không thể sử dụng: function is_touch_device () {return !! ('ontouchstart' trong cửa sổ) || !! ('msmaxtouchpoint' trong hoa tiêu); };
sidonaldson

sử dụng hàm sẽ hoạt động nhưng tôi thường thích sử dụng phương thức biến ở trên để nó chỉ được kiểm tra một lần và nhanh hơn khi tôi kiểm tra lại trong mã của mình. Ngoài ra, tôi thấy rằng tôi cần phải kiểm tra xem liệu msMaxTouchPoints có nhiều hơn 0 vì IE 10 trên Windows 8 không có màn hình cảm ứng có trả về 0 như msMaxTouchPoints không.
David

trả lại true về Firefox 32 của tôi trên windows 7 :(
vsync

Cả Firefox 33 và 33.1 trên Windows 8 đều hiển thị sai trên hệ thống của tôi. Nếu bạn nâng cấp Firefox của bạn lên phiên bản mới nhất thì nó vẫn trả về đúng không? Bạn có thể có một thiết bị được cài đặt trên máy của bạn có thể khiến Firefox nghĩ sai rằng máy của bạn đã chạm không?
David

>>> 'ontouchstart' trong cửa sổ >>> đúng FF 51.0.1 trên ubfox
Ravi Gadhia

25

Kể từ khi giới thiệu các tính năng phương tiện tương tác, bạn chỉ có thể làm:

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

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

Cập nhật (do nhận xét): Giải pháp trên là phát hiện xem "con trỏ thô" - thường là màn hình cảm ứng - là thiết bị đầu vào chính. Trong trường hợp bạn muốn phát hiện ra nếu một thiết bị có ví dụ chuột cũng có màn hình cảm ứng bạn có thể sử dụng any-pointer: coarsethay thế.

Để biết thêm thông tin, hãy xem tại đây: Phát hiện trình duyệt không có chuột và chỉ có cảm ứng


3
Đây là giải pháp tốt nhất, cảm ơn bạn! Mặc dù tôi sẽ khuyên bạn nên sử dụng (pointer: coarse)vì rất có thể bạn chỉ nhắm mục tiêu đầu vào chính. Có thể được sử dụng trong sản xuất, vì một số trình duyệt không hỗ trợ chỉ dành cho máy tính để bàn. Có một bài viết tuyệt vời về điều này trên css-trick .
Fabian von Ellerts

2
Đây là giải pháp duy nhất tôi đã thử nghiệm hoạt động trong mọi tình huống. Cảm ơn!
kaiserkiwi

20

Tôi thích cái này:

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

alert(isTouchDevice());

12
Không cần phải sử dụng biểu thức ternary để trả về boolean. Đơn giản chỉ cần sử dụng biểu thức để trả về boolean. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Tim Vermaelen

1
Bạn cũng có thể chỉ sử dụng: var isTouch = 'ontouchstart' in window;tuy nhiên điều này không hoạt động với Chrome mới nhất (v31), var isTouch = 'createTouch' in window.document;vẫn hoạt động.
Olivier

2
Như đã đề cập trong các ý kiến ​​của câu hỏi được chấp nhận trước đó. "Modernizr không kiểm tra màn hình cảm ứng. Nó kiểm tra sự tồn tại của các sự kiện cảm ứng trong trình duyệt". Chức năng của bạn là về mặt kỹ thuật hasTouchEvents () không phải làTouchDevice ()
hexalys

Lưu ý rằng việc kiểm tra các phương thức tương tự touchstartsẽ không thể nhận ra Surface là một thiết bị cảm ứng vì IE sử dụng pointercác sự kiện thay thế.
CookieMonster

1
Có thể @Nis đã đúng, nhưng trong Firefox 39, nó trả về sai.
Dan Dascalescu

17

Nếu bạn sử dụng Modernizr , nó rất dễ sử dụng Modernizr.touchnhư đã đề cập trước đó.

Tuy nhiên, tôi thích sử dụng kết hợp Modernizr.touchthử nghiệm tác nhân người dùng và để an toàn.

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
    }

Nếu bạn không sử dụng Modernizr, bạn chỉ cần thay thế Modernizr.touchchức năng trên bằng('ontouchstart' in document.documentElement)

Cũng lưu ý rằng việc kiểm tra tác nhân người dùng iemobilesẽ cung cấp cho bạn phạm vi rộng hơn của các thiết bị di động Microsoft được phát hiện hơn Windows Phone.

Cũng xem câu hỏi SO này


8
Rất nhiều điểm thưởng cho "làm điều gì đó cảm động" và "không thể chạm vào điều này"
Lee Saxon

bạn đang kiểm tra nhiều lần cho cùng một thiết bị và thực hiện nhiều Quy tắc khi bạn có thể sử dụng chỉ một. Thêm vào đó, bạn đang thực hiện các biểu thức không phân biệt chữ hoa chữ thường nhưng chuỗi đã được hạ thấp.
caesarsol

1
điều này là đủ:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
caesarsol

Bất kỳ lý do để viết thường hoặc làm cho trường hợp phù hợp không nhạy cảm? Khi nào "iOS", "Android" hoặc "IEMobile" sẽ sử dụng các vỏ khác?
Henrik N

14

Chúng tôi đã thử triển khai Modernizr, nhưng việc phát hiện các sự kiện chạm không còn phù hợp nữa (IE 10 có các sự kiện chạm trên máy tính để bàn windows, IE 11 hoạt động, vì đã bỏ các sự kiện chạm và thêm con trỏ api).

Vì vậy, chúng tôi đã quyết định tối ưu hóa trang web dưới dạng một trang web cảm ứng miễn là chúng tôi không biết loại đầu vào của người dùng. Điều này đáng tin cậy hơn bất kỳ giải pháp nào khác.

Các nghiên cứu của chúng tôi cho biết, hầu hết người dùng máy tính để bàn di chuyển bằng chuột trên màn hình trước khi họ nhấp, vì vậy chúng tôi có thể phát hiện ra họ và thay đổi hành vi trước khi họ có thể nhấp hoặc di chuột bất cứ thứ gì.

Đây là phiên bản đơn giản hóa mã của chúng tôi:

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

máy tính ngày nay có cả cảm ứng và chuột ... bạn phải phân biệt. đó là điều tuyệt đối phải biết nếu chỉ chạm, chuột hoặc cả hai. 3 trạng thái khác nhau.
vsync

1
Vâng, bạn đúng, nhưng điều này rất khó. Trong trường hợp tốt nhất, ứng dụng của bạn được thiết kế để sử dụng bởi bất kỳ bộ điều khiển đầu vào nào và không quan tâm nếu người dùng có màn hình cảm ứng, chuột, bàn phím hoặc tất cả cùng nhau.
Martin Lantzsch

1
Hành vi của người dùng có giá trị hơn một thông tin thực sự về loại thiết bị mà người dùng có. Khi bạn biết người dùng có chuột, màn hình cảm ứng và bàn phím - thì sao? Xử lý các hành vi (mousemove, touchmove, keydown, v.v.). Người dùng có thể thay đổi loại đầu vào của họ tại "thời gian chạy", đây là một vấn đề nghiêm trọng thực sự, khi bạn đang phát triển một ứng dụng thực tế được sử dụng 8 đến 5 mà không cần tải lại.
Martin Lantzsch

2
+1 Thực tế đây là câu trả lời tốt nhất cho tôi. Ví dụ, tôi có datagrids. Các bảng dữ liệu này sẽ hiển thị "biểu tượng chỉnh sửa" để chạm để chỉnh sửa hoặc menu ngữ cảnh để có thêm tùy chọn. Nếu di chuyển chuột được phát hiện, sau đó tôi xóa biểu tượng (tiết kiệm không gian trên lưới) và người dùng có thể nhấp đúp hoặc nhấp chuột phải.
prograhammer

3
chrome trên thiết bị cảm ứng thỉnh thoảng kích hoạt mousemove
pstanton

9

Fiddle làm việc

Tôi đã đạt được nó như thế này;

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
}

không phát hiện máy tính bảng bề mặt windows
Dan Beaulieu

@DanBeaulieu bạn có thể vui lòng cụ thể cho thiết bị không, vì tôi có windows phone hoạt động tốt, tôi cũng đã sử dụng nó trong ứng dụng của mình là QA: ED, tôi sẽ kiểm tra lại và sẽ cập nhật câu trả lời. Xin lỗi vì sự bất tiện
Aamir Shahzad

Không chắc chắn năm nào, đó là một cửa sổ bề mặt chuyên nghiệp thuộc về đồng nghiệp. Sau khi thêm Modernizr, chúng tôi đã làm cho nó hoạt động.
Dan Beaulieu

Điều này đã báo cáo chính xác Non-Touch trên máy Windows 7 của tôi và chạm vào Máy tính xách tay Windows 8 với màn hình cảm ứng và điện thoại Android 4.4 MotoX.
Clay Nichols

Cung cấp một dương tính giả trong Chrome (46) trên máy Mac của tôi
Patrick Fabrizius

9

Có một điều tốt hơn là kiểm tra xem họ có touchScreen hay không, là kiểm tra xem họ có đang sử dụng hay không, cộng với việc kiểm tra dễ dàng hơn.

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

6

Cái này hoạt động tốt ngay cả trong máy tính bảng 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");
}
}

4

Tôi đã sử dụng các đoạn mã ở trên để phát hiện xem có cảm ứng hay không, do đó, iframe ưa thích của tôi sẽ hiển thị trên máy tính để bàn và không chạm. Tôi nhận thấy rằng Opera Mini cho Android 4.0 vẫn đang đăng ký dưới dạng thiết bị không cảm ứng khi chỉ sử dụng mã của blmstr. (Có ai biết tại sao không?)

Tôi đã kết thúc bằng cách sử dụng:

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

bạn có thể giải thích, tại sao bạn không sử dụng một cuộc gọi khớp duy nhất với một biểu thức chính quy /iPhone|iPod|iPad|Android|BlackBerry/không?
dùng907860

Opera Mini thực hiện kết xuất trên các máy chủ của Opera chứ không phải trên chính thiết bị, vì vậy nó hơi kỳ lạ theo cách đó.
bluesmoon

4

"Gotcha" lớn nhất với việc cố gắng phát hiện cảm ứng là trên các thiết bị lai hỗ trợ cả cảm ứng và bàn di chuột / chuột. Ngay cả khi bạn có thể phát hiện chính xác liệu thiết bị của người dùng có hỗ trợ cảm ứng hay không, điều bạn thực sự cần làm là phát hiện thiết bị đầu vào nào mà người dùng hiện đang sử dụng. Có một bài viết chi tiết về thách thức này và một giải pháp khả thi ở đây .

Về cơ bản, cách tiếp cận để tìm hiểu xem người dùng chỉ chạm vào màn hình hay sử dụng chuột / bàn di chuột thay vào đó là đăng ký cả a touchstartmouseoversự kiện trên trang:

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

Một hành động chạm sẽ kích hoạt cả hai sự kiện này, mặc dù trước đây ( touchstart) luôn luôn đầu tiên trên hầu hết các thiết bị. Vì vậy, dựa vào chuỗi sự kiện có thể dự đoán được này, bạn có thể tạo một cơ chế tự động thêm hoặc xóa một can-touchlớp vào gốc tài liệu để phản ánh loại đầu vào hiện tại của người dùng tại thời điểm này trên tài liệu:

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

Thêm chi tiết tại đây .


3

Kiểm tra bài đăng này , nó cung cấp một đoạn mã thực sự hay để biết phải làm gì khi thiết bị cảm ứng được phát hiện hoặc phải làm gì nếu sự kiện touchstart được gọi:

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

3

Tôi sẽ tránh sử dụng chiều rộng màn hình để xác định xem một thiết bị có phải là thiết bị cảm ứng hay không. Có màn hình cảm ứng lớn hơn 699px, hãy nghĩ đến Windows 8. Navigatior.userAgent có thể tốt để ghi đè các tư thế sai.

Tôi khuyên bạn nên kiểm tra vấn đề này trên Modernizr.

Bạn có muốn kiểm tra xem thiết bị có hỗ trợ các sự kiện chạm hay là thiết bị cảm ứng. Thật không may, đó không phải là điều tương tự.


3

Không, nó không thể. Các câu trả lời xuất sắc được đưa ra chỉ là một phần, bởi vì bất kỳ phương pháp nào cũng sẽ tạo ra dương tính giả và phủ định sai. Ngay cả trình duyệt cũng không biết có màn hình cảm ứng hay không, do API hệ điều hành và thực tế có thể thay đổi trong phiên trình duyệt, đặc biệt là với các sắp xếp kiểu KVM.

Xem thêm chi tiết trong bài viết tuyệt vời này:

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

Bài báo đề nghị bạn xem xét lại các giả định khiến bạn muốn phát hiện màn hình cảm ứng, có lẽ họ đã sai. (Tôi đã tự kiểm tra ứng dụng của mình và các giả định của tôi thực sự sai!)

Bài báo kết luận:

Đối với bố cục, giả sử mọi người đều có màn hình cảm ứng. Người dùng chuột có thể sử dụng các điều khiển UI lớn dễ dàng hơn nhiều so với người dùng cảm ứng có thể sử dụng các điều khiển nhỏ. Điều tương tự cũng xảy ra đối với các trạng thái di chuột.

Đối với các sự kiện và tương tác, giả sử bất kỳ ai cũng có thể có màn hình cảm ứng. Thực hiện các tương tác bàn phím, chuột và cảm ứng với nhau, đảm bảo không chặn nhau.


3

Nhiều trong số này hoạt động nhưng yêu cầu jQuery hoặc linters khiếu nại về cú pháp. Xem xét câu hỏi ban đầu của bạn yêu cầu một cách giải quyết "JavaScript" (không phải jQuery, không phải Modernizr), đây là một chức năng đơn giản hoạt động mọi lúc. Nó cũng tối thiểu như bạn có thể nhận được.

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

console.log(isTouchDevice());

Một lợi ích cuối cùng tôi sẽ đề cập là mã này là bất khả tri về khung và thiết bị. Thưởng thức!


function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Điều này làm việc cho tôi, vì vậy tôi ở đây thêm một đóng góp cho câu trả lời này, vì tôi cũng đang mong đợi một chủ đề JS vanilla khi Google đưa tôi đến đây.
Daniel Lavedonio de Lima

2

Có vẻ như Chrome 24 hiện hỗ trợ các sự kiện chạm, có thể dành cho Windows 8. Vì vậy, mã được đăng ở đây không còn hoạt động. Thay vì cố gắng phát hiện xem cảm ứng có được trình duyệt hỗ trợ hay không, giờ đây tôi ràng buộc cả hai sự kiện chạm và nhấp và đảm bảo chỉ có một lệnh được gọi:

myCustomBind = function(controlName, callback) {

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

    callback.call();
  });
};

Và sau đó gọi nó:

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

Hi vọng điêu nay co ich !



2

Tất cả các trình duyệt được hỗ trợ ngoại trừ Firefox cho máy tính để bàn luôn ĐÚNG vì Firefox cho máy tính để bàn hỗ trợ thiết kế đáp ứng cho nhà phát triển ngay cả khi bạn nhấp vào Nút cảm ứng hay không!

Tôi hy vọng Mozilla sẽ sửa lỗi này trong phiên bản tiếp theo.

Tôi đang sử dụng máy tính để bàn Firefox 28.

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

nó vẫn là phiên bản 32.0 và họ chưa sửa nó! điên. Tại sao điều này không thể ăn được ?? Điều này luôn trả về true:(
vsync

2

jQuery v1.11.3

Có rất nhiều thông tin tốt trong các câu trả lời được cung cấp. Nhưng, gần đây tôi đã dành rất nhiều thời gian để cố gắng thực sự gắn kết mọi thứ lại với nhau thành một giải pháp hiệu quả cho việc hoàn thành hai điều:

  1. Phát hiện thiết bị đang sử dụng là thiết bị loại màn hình cảm ứng.
  2. Phát hiện thiết bị đã khai thác.

Bên cạnh bài đăng này và Phát hiện các thiết bị màn hình cảm ứng bằng Javascript , tôi thấy bài đăng này của Patrick Lauke cực kỳ hữu ích: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

Đây là mã ...

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

Quan trọng! Các*.on( events [, selector ] [, data ], handler ) nhu cầu phương pháp để có một chọn, thường là một yếu tố, có thể xử lý các "touchstart" sự kiện, hoặc bất kỳ khác như sự kiện gắn liền với chạm. Trong trường hợp này, đó là phần tử siêu liên kết "a".

Bây giờ, bạn không cần phải xử lý việc nhấp chuột thông thường trong JavaScript, bởi vì bạn có thể sử dụng CSS để xử lý các sự kiện này bằng cách sử dụng các bộ chọn cho phần tử "a" siêu liên kết như vậy:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Lưu ý: Có nhiều bộ chọn khác nữa ...


1
var isTouchScreen = 'createTouch' in document;

hoặc là

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

Tôi sẽ kiểm tra kỹ lưỡng hơn.


3
Nó sẽ là tốt để lưu ý rằng uađề cập đến navigator.userAgent. Ngoài ra, việc phát hiện theo chiều rộng màn hình có thể cho kết quả sai nếu ai đó mở trình duyệt ở chế độ không toàn màn hình.
HoLyVieR

1

Tôi sử dụng:

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

trong jQuery mobile 1.0.1


1

Tôi cũng đã vật lộn rất nhiều với các tùy chọn khác nhau về cách phát hiện trong Javascript cho dù trang có được hiển thị trên thiết bị màn hình cảm ứng hay không. IMO, cho đến nay, không có tùy chọn thực sự tồn tại để phát hiện tùy chọn đúng. Các trình duyệt báo cáo các sự kiện chạm trên máy tính để bàn (vì HĐH có thể sẵn sàng chạm) hoặc một số giải pháp không hoạt động trên tất cả các thiết bị di động.

Cuối cùng, tôi nhận ra rằng tôi đã làm theo cách tiếp cận sai ngay từ đầu: Nếu trang của tôi trông tương tự trên các thiết bị cảm ứng và không chạm, tôi có lẽ không nên lo lắng về việc phát hiện tài sản: Kịch bản của tôi là để hủy kích hoạt các chú giải công cụ trên các nút trên thiết bị cảm ứng khi chúng dẫn đến chạm hai lần trong đó tôi muốn một lần chạm để kích hoạt nút.

Giải pháp của tôi là cấu trúc lại khung nhìn sao cho không cần chú giải công cụ qua nút và cuối cùng tôi không cần phải phát hiện thiết bị cảm ứng từ Javascript bằng các phương pháp mà tất cả đều có nhược điểm .


1

Bạn có thể cài đặt hiện đại hóa và sử dụng một sự kiện cảm ứng đơn giản. Điều này rất hiệu quả và hoạt động trên mọi thiết bị tôi đã thử nghiệm trên cả bề mặt cửa sổ!

Tôi đã tạo một 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;
    }
}

3
Chào mừng đến với SO! Mã tự nó (như mã không bị lỗi) hiếm khi tạo thành một câu trả lời. Bạn có thể cải thiện câu trả lời này bằng cách thêm một lời giải thích về đoạn trích.
ebarr

1

Câu trả lời thực tế dường như là một câu hỏi xem xét bối cảnh:

1) Trang web công cộng (không đăng nhập)
Mã UI để hoạt động với cả hai tùy chọn cùng nhau.

2) Trang web đăng nhập
Nắm bắt xem liệu di chuyển chuột có xảy ra trên biểu mẫu đăng nhập hay không và lưu nó vào một đầu vào ẩn. Giá trị được thông qua với thông tin đăng nhập và được thêm vào phiên của người dùng , vì vậy nó có thể được sử dụng trong suốt thời gian của phiên.

Jquery chỉ thêm vào trang đăng nhập:

$('#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 đến @Dave Burt và +1 cho @Martin Lantzsch về câu trả lời của họ)


1

Vấn đề

Do các thiết bị lai sử dụng kết hợp đầu vào cảm ứng và chuột, bạn cần có khả năng linh hoạt thay đổi trạng thái / biến điều khiển xem một đoạn mã có nên chạy nếu người dùng là người dùng cảm ứng hay không.

Thiết bị cảm ứng cũng cháy mousemove vào vòi.

Giải pháp

  1. Giả sử cảm ứng là sai khi tải.
  2. Đợi cho đến khi một touchstartsự kiện được kích hoạt, sau đó đặt nó thành sự thật.
  3. Nếu touchstart bị sa thải, hãy thêm một trình xử lý mousemove.
  4. Nếu thời gian giữa hai sự kiện mousemove bắn ít hơn 20ms, giả sử họ đang sử dụng chuột làm đầu vào. Xóa sự kiện vì nó không còn cần thiết và mousemove là một sự kiện đắt tiền cho các thiết bị chuột.
  5. Ngay khi touchstart được kích hoạt lại (người dùng quay lại sử dụng cảm ứng), biến được đặt trở lại đúng. Và lặp lại quá trình để nó được xác định theo kiểu năng động. Nếu bởi một số mousemove thần kỳ bị bắn hai lần một cách vô lý một cách nhanh chóng (trong thử nghiệm của tôi thì hầu như không thể làm điều đó trong vòng 20ms), lần chạm tiếp theo sẽ đưa nó trở lại đúng.

Đã thử nghiệm trên Safari iOS và Chrome cho Android.

Lưu ý: không chắc chắn 100% về các sự kiện con trỏ cho MS Surface, v.v.

Bản demo 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);
}

1

Trên thực tế, tôi đã nghiên cứu câu hỏi này và xem xét tất cả các tình huống. bởi vì nó là một vấn đề lớn trong dự án của tôi quá. Vì vậy, tôi đạt đến chức năng dưới đây, nó hoạt động cho tất cả các phiên bản của tất cả các trình duyệt trên tất cả các thiết bị:

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

Gợi ý : Chắc chắn,isTouchDevicechỉ trả vềbooleangiá trị.


0

supportĐối tượng jQuery mở rộng :

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

Và bây giờ bạn có thể kiểm tra nó ở bất cứ đâu, như thế này:

if( jQuery.support.touch )
   // do touch stuff

0

Điều này dường như đang làm việc tốt cho tôi cho đến nay:

//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)
}

0

Khi một con chuột được gắn vào, nó có thể được giả định với tỷ lệ trúng khá cao (thực tế tôi sẽ nói 100%) rằng người dùng di chuyển chuột ít nhất một khoảng cách nhỏ sau khi trang sẵn sàng - mà không cần nhấp chuột. Cơ chế dưới đây phát hiện điều này. Nếu được phát hiện, tôi coi đây là dấu hiệu của hỗ trợ cảm ứng bị thiếu hoặc, nếu được hỗ trợ, có tầm quan trọng nhỏ khi sử dụng chuột. Thiết bị cảm ứng được giả sử nếu không được phát hiện.

BIÊN TẬP Cách tiếp cận này có thể không phù hợp với tất cả các mục đích. Nó có thể được sử dụng để kiểm soát chức năng được kích hoạt dựa trên tương tác của người dùng trên trang được tải, ví dụ như trình xem hình ảnh. Mã dưới đây cũng sẽ để lại sự kiện mousemove bị ràng buộc trên các thiết bị không có chuột như hiện tại. Các cách tiếp cận khác có thể tốt hơn.

Roughly, nó đi như thế này (xin lỗi cho jQuery, nhưng tương tự trong Javascript thuần túy):

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;
}));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.