Я разрабатываю веб-приложение (не веб-сайт со страницами с интересным текстом) с совершенно другим интерфейсом для касания (ваш палец скрывает экран при нажатии) и мыши (в значительной степени зависит от предварительного просмотра при наведении курсора). Как я могу обнаружить, что у моего пользователя нет мыши, чтобы предоставить ему правильный интерфейс? Я планирую оставить переключатель для людей с мышью и сенсорным (как некоторые ноутбуки).
Возможность сенсорного события в браузере на самом деле не означает, что пользователь использует сенсорное устройство (например, Modernizr его не отключает). Код, который правильно отвечает на вопрос, должен возвращать false, если на устройстве есть мышь, в противном случае - true. Для устройств с мышью и сенсорным экраном он должен возвращать false (не только сенсорный)
В качестве примечания, мой сенсорный интерфейс может также подойти для устройств только с клавиатурой, так что я скорее хочу обнаружить отсутствие мыши.
Чтобы прояснить необходимость, вот API, который я ищу для реализации:
// Level 1
// The current answers provide a way to do that.
hasTouch();
// Returns true if a mouse is expected.
// Note: as explained by the OP, this is not !hasTouch()
// I don't think we have this in the answers already, that why I offer a bounty
hasMouse();
// Level 2 (I don't think it's possible, but maybe I'm wrong, so why not asking)
// callback is called when the result of "hasTouch()" changes.
listenHasTouchChanges(callback);
// callback is called when the result of "hasMouse()" changes.
listenHasMouseChanges(callback);
источник
Ответы:
Основная проблема заключается в том, что у вас есть следующие различные классы устройств / вариантов использования:
Хуже всего то, что можно переходить от некоторых из этих классов к другим (подключать мышь, подключать к клавиатуре), или пользователь может ВИДЕТЬ, что он находится на обычном ноутбуке, пока не дотянется и не коснется экрана.
Вы правы, предполагая, что присутствие конструкторов событий в браузере не является хорошим способом для продвижения вперед (и это несколько противоречиво). Кроме того, если вы не отслеживаете очень конкретное событие или не пытаетесь исключить только несколько классов выше, использование самих событий не является полным доказательством.
Например, скажем, вы обнаружили, что пользователь испустил реальное движение мыши (не ложное от событий касания, см. Http://www.html5rocks.com/en/mobile/touchandmouse/ ).
Тогда что?
Вы включаете стили наведения? Вы добавляете больше кнопок?
В любом случае вы увеличиваете время на стекло, потому что вам нужно ждать, пока событие сработает.
Но что произойдет, когда ваш благородный пользователь решит отключить свою мышь и полностью прикоснуться к ней ... Вы ждете, пока он коснется вашего теперь переполненного интерфейса, а затем измените его сразу после того, как он попытался точно определить ваш теперь переполненный пользовательский интерфейс?
В виде маркера, цитируя штукатурку на https://github.com/Modernizr/Modernizr/issues/869#issuecomment-15264101
Кроме того: браузер знает, когда пользователь подключает мышь / подключается к клавиатуре, но не открывает ее для JavaScript ... черт!
Это должно привести вас к следующему:
Идея прогрессивного улучшения здесь вполне применима. Создайте опыт, который работает гладко, независимо от контекста пользователя. Затем сделайте предположения, основанные на функциях браузера / медиазапросах, чтобы добавить функциональность, которая будет относительной в предполагаемом контексте. Присутствие мыши - это лишь один из множества способов, которыми разные пользователи на разных устройствах воспринимают ваш сайт. Создайте что-нибудь с достоинствами в своем ядре и не беспокойтесь о том, как люди нажимают на кнопки.
источник
:hover
элементы и тому подобное), когда пользователь переключается с мыши на сенсорное. Кажется маловероятным, что пользователь в настоящее время использует мышь + касание в одно и то же время (я имею в виду comoonn, это как подключить 2 мыши к одному и тому же компьютеру, хахаха)Как насчет прослушивания события mousemove в документе. Затем, пока вы не услышите это событие, вы предполагаете, что устройство сенсорное или только клавиатурное.
(Где
listen
иunlisten
делегироватьaddEventListener
или поattachEvent
мере необходимости.)Надеюсь, это не приведет к слишком большому визуальному рывку, это будет отстой, если вам понадобятся массивные повторные макеты, основанные на режиме ...
источник
Начиная с 2018 года, существует хороший и надежный способ определить, есть ли в браузере мышь (или подобное устройство ввода): функции взаимодействия с мультимедиа в CSS4, которые теперь поддерживаются практически любым современным браузером (кроме IE 11 и специальных мобильных браузеров).
W3C:
Смотрите следующие варианты:
Медиа-запросы также могут быть использованы в JS:
Связанный:
Документация W3: https://www.w3.org/TR/mediaqueries-4/#mf-interaction
Поддержка браузера: https://caniuse.com/#search=media%20features
Аналогичная проблема: определить, поддерживает ли клиентское устройство состояния: hover и: focus
источник
Ответ @ Wyatt великолепен и дает нам много о чем подумать.
В моем случае я предпочел прислушиваться к первому взаимодействию, чтобы только потом установить поведение. Поэтому, даже если у пользователя есть мышь, я буду воспринимать ее как сенсорное устройство, если первое взаимодействие было касанием.
Учитывая данный порядок, в котором обрабатываются события :
Можно предположить, что если событие мыши запускается до касания, это настоящее событие мыши, а не эмуляция. Пример (с использованием jQuery):
Это сработало для меня
источник
Можно только определить, поддерживает ли браузер сенсорный ввод . Нет способа узнать, подключен ли к нему сенсорный экран или мышь.
Можно расставить приоритеты использования, хотя, прослушивая событие касания вместо события мыши, если обнаружена возможность касания.
Чтобы обнаружить сенсорные возможности кросс-браузера:
Затем можно использовать это, чтобы проверить:
или выбрать событие для прослушивания:
или используйте отдельные подходы для сенсорного или не сенсорного:
Для мыши можно только определить, используется ли мышь, а не существует она или нет. Можно установить глобальный флаг, чтобы указать, что мышь была обнаружена при использовании (аналогично существующему ответу, но немного упрощенному):
(нельзя включить
mouseup
или,mousedown
поскольку эти события также могут быть вызваны касанием)Браузеры ограничивают доступ к низкоуровневым системным API-интерфейсам, которые необходимы для обнаружения таких функций, как аппаратные возможности системы, в которой они используются.
Существует возможность, возможно, написать плагин / расширение для доступа к ним, но через JavaScript и DOM такое обнаружение ограничено для этой цели, и нужно будет написать плагин, специфичный для различных платформ ОС.
Итак, в заключение: такое обнаружение может быть оценено только по «хорошей догадке».
источник
Когда Media Queries Level 4 доступен в браузерах, мы сможем использовать запросы «указатель» и «зависание» для обнаружения устройств с помощью мыши.
Если мы действительно хотим передать эту информацию в Javascript, мы могли бы использовать CSS-запрос для установки определенных стилей в соответствии с типом устройства, а затем использовать
getComputedStyle
в Javascript для чтения этого стиля и извлечения из него исходного типа устройства.Но мышь может быть подключена или отключена в любое время, и пользователь может захотеть переключаться между касанием и мышью. Поэтому нам может потребоваться обнаружить это изменение и предложить изменить интерфейс или сделать это автоматически.
источник
any-pointer
иany-hover
позволит вам изучить все применимые возможности устройства. Приятно взглянуть на то, как мы могли бы решить эту проблему в будущем! :)Поскольку вы планируете в любом случае предложить способ переключения между интерфейсами, возможно ли будет просто попросить пользователя щелкнуть ссылку или кнопку, чтобы «ввести» правильную версию приложения? Тогда вы могли вспомнить их предпочтения для будущих посещений. Это не хай-тек, но это на 100% надежно :-)
источник
@SamuelRossille К сожалению, нет браузеров, в которых мне известно о существовании (или его отсутствии) мыши.
Итак, с учетом всего сказанного, мы просто должны постараться и сделать все возможное с нашими существующими опциями ... событиями. Я знаю, что это не совсем то, что вы ищете ... согласился, что это далеко от идеала.
Мы можем сделать все возможное, чтобы выяснить, использует ли пользователь мышь или сенсорный в любой момент. Вот быстрый и грязный пример использования jQuery & Knockout:
Теперь вы можете привязать / подписаться на usingMouse () и usingTouch () и / или стилизовать ваш интерфейс с классом body.mouse . Интерфейс будет переключаться вперед и назад, как только будет обнаружен курсор мыши, и при сенсорном запуске.
Надеюсь, у нас скоро появятся лучшие варианты от поставщиков браузеров.
источник
Tera-WURFL может рассказать вам о возможностях устройства, которое посещает ваш сайт , сравнив сигнатуру браузера с его базой данных. Посмотрите, это бесплатно!
источник
Почему бы вам просто не определить, обладает ли он способностью ощущать прикосновения и / или реагировать на движения мыши?
источник
has_touch = 'ontouchstart' in window
хватит и тд.Это сработало для меня в аналогичной ситуации. По сути, предположим, что у пользователя нет мыши, пока вы не увидите короткую серию последовательных движений мыши, без вмешательства мышами или мышиных мышек. Не очень элегантно, но это работает.
источник
Взгляните на моденизр, одной из его особенностей является сенсорный
http://modernizr.com/docs/#features-misc
Пока я не проверил полностью, кажется, работает очень хорошо
Также это связано со страницей modernizr http://www.html5rocks.com/en/mobile/touchandmouse/
источник
Как указывали другие, окончательное определение наличия у них мыши ненадежно. Это может легко измениться, в зависимости от устройства. Это определенно то, что вы не можете надежно сделать с логическим значением true или false, по крайней мере, в масштабе документа.
События касания и события мыши являются эксклюзивными. Так что это может несколько помочь при совершении различных действий. Проблема в том, что события касания находятся ближе к событиям мыши вверх / вниз / перемещения, а также вызывают событие щелчка.
От вашего вопроса вы говорите, что хотите иметь предварительный просмотр. Кроме того, я не знаю никаких других особенностей вашего интерфейса. Я предполагаю, что при отсутствии мыши вы хотите, чтобы касание предварительно просматривалось, в то время как щелчок выполняет другое действие из-за всплывающего предварительного просмотра.
Если это так, вы можете использовать ленивый подход к обнаружению:
Событию onclick всегда будет предшествовать событие onmouseover с мышью. Поэтому запомните, что мышь находится над элементом, по которому щелкнули.
Вы можете сделать это с помощью события onmousemove для всего документа. Вы можете использовать
event.target
для записи, на каком элементе находится мышь. Затем внутри событий onclick вы можете проверить, находится ли мышь на самом деле над элементом, по которому щелкают (или потомком элемента).Оттуда вы можете выбрать либо использовать событие click для обоих, и выполнить действие A или B в зависимости от результата. Действие B может быть ничем, если некоторые сенсорные устройства не генерируют событие щелчка (вместо этого вы должны полагаться на события ontouch *).
источник
Я не думаю, что можно идентифицировать устройство только для касания (насколько мне известно, конечно). Основная проблема заключается в том, что все события мыши и клавиатуры запускаются сенсорными устройствами. В следующем примере оба оповещения возвращают значение true для сенсорных устройств.
источник
true
на'onmousedown' in window
На мой взгляд, лучшая идея - это
mousemove
слушатель (в настоящее время лучший ответ). Я считаю, что этот метод нужно немного доработать. Это правда, что сенсорные браузеры эмулируют даже событие mousemove, как вы можете видеть в этом обсуждении iOS , поэтому мы должны быть немного осторожнее.Имеет смысл, что сенсорные браузеры будут эмулировать это событие только тогда, когда пользователь нажимает на экран (палец пользователя опущен). Это означает, что мы должны добавить тест во время нашего обработчика перемещения мыши, чтобы увидеть, какая кнопка мыши нажата (если есть) во время события. Если ни одна кнопка мыши не нажата, мы можем с уверенностью предположить, что настоящая мышь присутствует. Если кнопка мыши нажата, тест остается безрезультатным.
Так как это будет реализовано? Этот вопрос показывает, что самый надежный способ выяснить, какая кнопка мыши нажата во время перемещения мыши, - это фактически прослушивать 3 события на уровне документа: mousemove, mousedown и mouseup. Вверх и вниз будет установлен только глобальный логический флаг. Ход выполнит тест. Если у вас есть ход и логическое значение ложно, мы можем предположить, что мышь присутствует. Смотрите вопрос для точных примеров кода.
Один последний комментарий. Этот тест не идеален, потому что он не может быть выполнен во время загрузки. Поэтому я бы использовал прогрессивный метод улучшения, как было предложено ранее. По умолчанию отображается версия, которая не поддерживает специфический для мыши интерфейс наведения мыши. Если мышь обнаружена, включите этот режим во время выполнения с помощью JS. Это должно выглядеть как можно более незаметно для пользователя.
Чтобы поддержать изменения в конфигурации пользователя (т. Е. Мышь была отключена), вы можете периодически повторно тестировать. Хотя я полагаю, что в этом случае будет лучше просто уведомить пользователя о двух режимах и позволить пользователям вручную переключаться между ними (как, например, выбор мобильного / настольного компьютера, который всегда можно изменить).
источник
Провел несколько тестов на разных ПК, Linux, iPhone, Android телефонах и вкладках. Странно, что нет простого пуленепробиваемого решения. Проблема возникает, когда некоторые приложения, в которых есть Touch и мышь не по-прежнему представляют события Touch и Mouse в приложении. Поскольку мы хотим поддерживать экземпляры только для мыши и только для касания, хотим обрабатывать оба, но это вызывает двойное возникновение пользовательских взаимодействий. Если может знать, что мышь не присутствует на устройстве, то может знать, чтобы игнорировать ложные / вставленные события мыши. Попытка установки флага, если встречается MouseMove, но некоторые браузеры выдают поддельные MouseMove, а также MouseUp и MouseDown. Пробовал изучать временные метки, но решил, что это слишком рискованно. Итог: я обнаружил, что браузеры, создавшие ложные события мыши, всегда вставляли один MouseMove непосредственно перед вставленным MouseDown. В 99,99% моих случаев при работе в системе с настоящей мышью происходит несколько последовательных событий MouseMove - не менее двух. Поэтому следите за тем, встречает ли система два последовательных события MouseMove, и объявляйте, что мыши нет, если это условие никогда не выполняется. Это, вероятно, слишком просто, но работает на всех моих тестовых установках. Думаю, я буду придерживаться этого, пока не найду лучшее решение. - Джим В.
источник
Простое решение в jQuery для обнаружения использования мыши, которое решает проблему, при которой мобильные устройства также вызывают событие mousemove. Просто добавьте слушателя сенсорного запуска, чтобы удалить слушателя перемещения мыши, чтобы он не срабатывал при касании.
Конечно, устройство все еще может быть сенсорной и мышью, но вышеизложенное гарантирует, что использовалась настоящая мышь.
источник
Только что нашел решение, которое я считаю довольно элегантным.
источник
Я столкнулся с той же самой проблемой, где одно касание было также зарегистрировано как щелчок. После того, как я прочитал комментарии самых популярных ответов, я нашел собственное решение:
Единственная проблема, которую я обнаружил, заключается в том, что вы должны иметь возможность прокрутки, чтобы правильно обнаружить сенсорное событие. одна вкладка (касание) может создать проблемы.
источник
Я часами разбирался с этой проблемой для своего приложения Phonegap и придумал этот хак. Он генерирует консольное предупреждение, если вызванное событие является «пассивным» событием, то есть оно не вызывает никаких изменений, но работает! Я был бы заинтересован в любых идеях для улучшения или лучшего метода. Но это эффективно позволяет мне использовать $ .touch () повсеместно.
источник
Основная проблема, которую я вижу здесь, состоит в том, что большинство сенсорных устройств запускают событие мыши вместе с отвечающим за одно касание ядром (touchstart -> mousedown, touchmove -> mousemove и т. д.). Только для клавиатуры, наконец, для современных, они имеют универсальный браузер, поэтому вы даже не можете обнаружить присутствие класса MouseEvent.
На мой взгляд, менее болезненным решением было бы, по моему мнению, отображать меню при запуске (с управлением «alt» для пользователей только с клавиатуры) и, возможно, сохранить выбор с помощью localStorage / cookies / serveride или же оставить тот же выбор следующим время посетитель приходит
источник
Я настоятельно рекомендую против такого подхода. Рассмотрите устройства с сенсорным экраном, размером с настольный компьютер, и у вас есть другой набор проблем, которые нужно решить.
Пожалуйста, сделайте ваше приложение пригодным для использования без мыши (т.е. без предварительного просмотра).
источник
Хотел бы порекомендовать скрипта, который мне помог:
Я прочитал и попробовал все предложенное, без достаточных результатов.
Тогда я исследовал еще немного и нашел этот код - device.js
Я использую это на веб-сайте моего клиента, чтобы обнаружить существование мыши:
(
<html>
должен иметьdesktop
класс), и это кажется довольно хорошим, и дляtouch
поддержки я просто делаю регулярную проверку'ontouchend' in document
и использую информацию из обоих обнаружений, чтобы предположить, что мне нужна конкретная вещь.источник
Как правило, лучше определить, поддерживается ли функция наведения мыши, а не определять тип ОС / браузера. Вы можете сделать это просто следующим образом:
Убедитесь, что вы не делаете следующее:
Последний на самом деле вызовет метод, а не проверит его существование.
Вы можете прочитать больше здесь: http://www.quirksmode.org/js/support.html
источник