Сервис для обнаружения типа устройства пользователя на typescript и vue

—

от автора

Так-с, уважаемые коллеги, всех радостно приветствую! Это небольшая статейка как раз для тех людей, которые хотят по быстрому вот такой функционал:

  • обнаруживать какой тип взаимодействия с веб приложением у пользователя: touchscreen, мышка, либо же и то, и другое одновременно

  • обнаруживать какая ориентация на данный момент у пользователя

  • обнаруживать какой тип устройства имеет пользователь: desktop, tab, phone

    Звучит, конечно, не сложно, но для этого нужно собирать своего трансформера с разных форумов, я же предлагаю свое решение в готовом и компактном виде 🙂

Перейдем к главному: логика и код

В общем и целом, мне нужен был такой функционал, который бы при первом заходе пользователя показывает touch это или нет. А далее уже можно подхватить и разные другие события. Делается это все для реактивной адаптивности, т.к. на css сделать это просто невозможно.

Перейдем к коду. Создадим для начала все нужные перечисления (enum) для дальнейшего взаимодействия:

  • InteractionType.ts — enum, отвечающий за тип взаимодействия — мышка, тач, либо оба сразу

export namespace InteractionType {     export enum State {         Unknown = 'Unknown',         Mouse = 'Mouse',         Touch = 'Touch',         Both =  'Both'     } }
  • OrientationType.ts — enum, отвечающий за тип ориентации — вертикаль, горизонталь, в рамках css это портрет и лэндскейп

export namespace OrientationType {     export enum State {         Unknown = 'Unknown',         Portrait = 'Portrait',         Landscape = 'Landscape',     } }
  • DeviceType.ts — enum, отвечающий за тип устройства — планшет, телефон, либо ПК

export namespace DeviceType {     export enum State {         Unknown = 'Unknown',         Desktop = 'Desktop',         Phone = 'Phone',         Tab = 'Tab'     } }

Теперь напишем сам класс, который будем подключать к компонентам. Начнем с самого простого — инициализация и объявление всех полей. Тут все по стандарту, ничего такого, разве что можно обратить внимание на параметр у addEventListener — once, т.к. нам не требуется отслеживать каждый раз что там у пользователя за тип, сработало раз — все, делаем отметку, что есть, например, тачскрин и больше этот обработчик не трогаем.

public interactionType: InteractionType.State; public orientationType: OrientationType.State; public deviceType: DeviceType.State;  constructor () {     this.interactionType = InteractionType.State.Unknown;     this.orientationType = OrientationType.State.Unknown;     this.deviceType = DeviceType.State.Unknown;      window.addEventListener('touchstart', this.activeTouchState, { once: true });     window.addEventListener('mousemove',  this.activeDeskState, { once: true }); }

Далее, в моем случае, мне нужно было отследить не только при первом действии, но и при заходе на сайт, поэтому я добавил такую функцию для первоначального определения тачскрина:

    public defineTouchscreen (): void {         if (window.PointerEvent && ('maxTouchPoints' in navigator)) {             // if Pointer Events are supported, just check maxTouchPoints             if (navigator.maxTouchPoints > 0) {                 this.activeTouchState();             }         } else {             // no Pointer Events...             if (window.matchMedia && window.matchMedia("(any-pointer:coarse)").matches) {                 // check for any-pointer:coarse which mostly means touchscreen                 this.activeTouchState();             } else if (window.TouchEvent || ('ontouchstart' in window)) {                 // last resort - check for exposed touch events API / event handler                 this.activeTouchState();             }         }     }

Теперь добавим функции обработчики для eventListener’ов:

    private activeTouchState (): void {         if (this.interactionType === InteractionType.State.Mouse) {             this.interactionType = InteractionType.State.Both;         } else {             this.interactionType = InteractionType.State.Touch;         }     }      private activeDeskState (): void {         if (this.interactionType === InteractionType.State.Touch) {             this.interactionType = InteractionType.State.Both;         } else {             this.interactionType = InteractionType.State.Mouse;         }     }

Думаю, объяснять много тут не надо — просто предусмотрел тут все случаи, когда пользователь с новороченным ноутбуком с тачпадом может кликнуть сначала мышкой, а потом перейти на тачпад. Также и обратно — начал с тачпада, перешел на мышь, в итоге оба взаимодействия.

Теперь функция для ориентации устройства:

    public defineDeviceType (): void {         const ua = navigator.userAgent;         if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {             this.deviceType = DeviceType.State.Tab;             return;         }         if (             /Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(                 ua             )         ) {             this.deviceType = DeviceType.State.Phone;             return;         }         this.deviceType = DeviceType.State.Desktop;     };

Единственное, что тут нужно знать, так это то, что navigator.userAgent возвращает строку вида:

userAgent = appCodeName/appVersion number (Platform; Security; OS-or-CPU; Localization; rv: revision-version-number) product/productSub Application-Name Application-Name-version

А дальше мы уже можем проводить столько проверок, сколько захотим.
Ну и осталась функция для определения ориентации устройства:

    public defineOrientationType (): void {         if (window.matchMedia("(orientation: portrait)").matches) {             this.orientationType = OrientationType.State.Portrait;         } else if (window.matchMedia("(orientation: landscape)").matches) {             this.orientationType = OrientationType.State.Landscape;         }     }

На этом код готов) Использовать можно следующим образом:

  • Импортнуть класс и enum’ы

  • Просто создать computed свойство для поля объекта класса и отслеживать его изменения

Вообще тут можно много всего сделать, нужно уже самому тыкаться и смотреть, что да как прикручивать.

С остальными функциями примерно то же самое — вешаем computed и наслаждаемся реактивностью изменения всех этих данных 🙂

Полный код как обычно на моем гитхабе

На этом желаю всем удачи! До встречи!


ссылка на оригинал статьи https://habr.com/ru/articles/748890/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *