Fun APIs

Семичев Олег

Speech Synthesis

Позволяет генерировать
синтезированную речь в браузере

Feature detection


if (window.speechSynthesis) {}
                

Methods


speechSynthesis
    .cancel()
    .pause()
    .resume()
    .speak()
    .getVoices()
                

var message = new SpeechSynthesisUtterance('Hello World');

window.speechSynthesis.speak(message);
                
Let's try!

Params


var voices = window.speechSynthesis.getVoices();

message.voice = voices[10]; // голос
message.rate  = 1;          // скорость от 0 до 10
message.pitch = 2;          // высота от 0 до 2
message.text  = 'Text';
message.lang  = 'en-US';
                

Events


message
    .onboundary  // при окончании слова/предложения
    .onend
    .onerror
    .onpause
    .onresume
    .onstart
                

Speech Synthesis

Specification
Support
Article
Demo

Speech Recognition

Позволяет распознавать человеческую
или синтезированную речь в браузере

Feature detection


var SpeechRecognition = window.SpeechRecognition     ||
                        window.webkitSpeechRecognition;
                

Params


var recognizer = new SpeechRecognition();
                

recognizer.lang = 'en-US';

// продолжает слушать и расопзнавать речь даже после паузы
recognizer.continuous = true;     // false по умолчанию

// повзоляет получать промежуточные результаты
recognizer.interimResults = true; // false по умолчанию
                

Methods


recognizer
    .start()
    .stop()
                

Events


recognizer
    .onstart
    .onend
    .onerror
    .onresult
                    

Event object


{
    resultIndex: 0,        // индекс текущего результата
    results : [            // 2d-массив результатов/слов
        [
            isFinal: true, // – законченный результат
            0: {           // [0] - самое вероятное слово
                confidence: 0.91233,
                transcript: 'Hi'
            },
            ...
        ],
        ...
    ]
}
                

<div id="speech-log">Click to start!</div>
                

var log = document.getElementById('speech-log');
                

var recognizer = new SpeechRecognition();

recognizer.lang = 'en-US';
recognizer.continious = true;
                

log.onclick = function () {
    log.innerHTML = 'Recognition started';
    recognizer.start();
};
                

recognizer.onresult = function (e) {
    var index = e.resultIndex;
    var result = e.results[index][0].transcript.trim();

    log.innerHTML = result;

    if (result.toLowerCase() === 'tequila') {
        log.innerHTML += '
Recognition stopped'; recognizer.stop(); } };
Click to start recognizing

Speech Recognition

Specification
Support
Article
Demo

Stream

Позволяет получать данные с различных устройств,
например микрофона или веб-камеры
DISCLAIMER
Стоит сразу заметить, что Stream это очень крупная, крайне специфичная и нестабильная тема, поэтому в контексте данной лекции будет рассказано о методе navigator.getUserMedia, который можно уже считать legacy, ибо в будущем он будет переписан и попадет в MediaDevices.

Тем не менее, этот метод всецело дает вам понять,
что умеют браузеры уже сейчас.

Feature detection


var getUserMedia = navigator.getUserMedia     ||
                   navigator.mozGetUserMedia  ||
                   navigator.webkitGetUserMedia;
                

Params


getUserMedia(
    options,
    function successCallback(stream) {},
    function errorCallback(error) {}
);
                

options = {
    video: true,
    audio: true
}
                

Constraints


options = {
    video: {
        // обязательные условия, которые должен
        // выполнить UA, иначе вызовется errorCallback
        mandatory: {
            minWidth    : 1280,
            minHeight   : 720,
            minFrameRate: 30
        },
        optional: [
            { minFrameRate: 60 }
        ]
    }
}
                
Подробнее в спеке

<video id="media-video"></video>
                

var video = document.getElementById('media-video');
                

var localStream = null;
                

video.onclick = function () {
    if (// поток активен) {
        // вырубаем его
    }

    // включаем
}
                

video.onclick = function () {
    if (// поток активен) {
        // вырубаем его
    }

    getUserMedia(
        { video: true, audio: true },
        function(mediaStream) {
            localStream = mediaStream;

            video.src = URL.createObjectURL(mediaStream);
            video.play();
        },
        function (error) { console.log(error); }
    );
};
                
О createObjectURL на MDN

video.onclick = function () {
    if (localStream && localStream.active) {
        var track = localStream.getTracks()[0];
        track.stop();

        video.pause();

        return;
    }

    // включаем
};
                

Stream

Specification
Support
Article
Demo

Ambient Light

Позволяет получать данные об уровне освещенности
с датчика света устройства
DISCLAIMER
Конструктор AmbientLightSensor, описанный в спецификации, не реализован нигде. Но существуют два события:
ondevicelight и onlightlevel, из которых работает
только одно – ondevicelight.

Feature detection


if ('ondevicelight' in window) {}
                

<div id="light-value"></div>
                

var lightValue = document.getElementById('light-value');

window.ondevicelight = function(e) {
    lightValue.innerHTML = 'Light is ' + e.value + ' lux';
};
                

Ambient Light

Specification
Support
Article
Demo

Gamepad

Интерфейс для обработки данных от usb-контроллера

Feature detection


if (navigator.getGamepads) {}
                

Get Gamepad


var gamepads = navigator.getGamepads();
// Chrome  - { 0, 1, 2, 3, length}
// Firefox - [ 0 ... n ]
// Edge    - [ undefined, undefined, undefined, undefined ]
                

var gamepad = gamepads[0];
// ???
                

Gamepad Props


gamepad
    .index
    .connected // true, если геймпад подключен
    .id        // информация о геймпаде,
               // напр. производитель, модель
    .timestamp // t последнего изменения состояния
               // (некоторые модели постоянно
               // пингуют браузер)
                

Gamepad Axes


gamepad
    // массив осей со значениями от -1 до 1:
    // -1 – вверх/влево
    //  1 – вниз/вправо
    //  0 – не нажато
    .axes [
        0: -1, // крестовина - горизонтальная ось
        1:  1, // крестовина - вертикальная ось
        ...
    ]
                

Возможны дробные значения для аналоговых стиков

Gamepad Buttons


gamepads
    .buttons: [
        0: {
            pressed: true,
            value: 1
        },
        ...
    ]
                

Аналоговые кнопки тоже имеют место быть

Gamepad Events


window.addEventListener('gamepadconnected', callback);
window.addEventListener('gamepaddisconnected', callback);
// e.gamepad - Gamepad Object
                

// Firefox only
window.addEventListener('gamepadbuttondown', callback);
window.addEventListener('gamepadbuttonup', callback);
// e.button – индекс нажатой кнопки
                

// Firefox Nightly only
window.addEventListener('gamepadaxismove', callback);
// e.axis – индекс оси, e.value – ее значение
                
Реализуем простенький логгер управления c геймпада.
Для этого выделим 4 действия:

  • идти влево (←)
  • идти вправо (→)
  • прыгнуть (B2)
  • атаковать (B3)


А как определять нажатие кнопок,
если события-хэлперы есть только в Firefox?

<pre id="gamepad-logger"></pre>
                

var logger = document.getElementById('gamepad-logger');
                

// какой-то хитрый бесконечный цикл в котором...
var gamepads = navigator.getGamepads()[0];
var gamepad = gamepads[0]; // ...получим геймпад
log(gamepad);              // ...и залогируем его
                
Это, в нашем случае, так называемый Game loop

Как мы можем реализовать этот game loop?


X while (true) { loop }



X setInterval(loop, 10);



X (loop { ... setTimeout(loop, 10) })();

window.requestAnimationFrame, дай мне сил!


(function loop() {
    var gamepad = navigator.getGamepads()[0];

    gamepad && log(gamepad);

    window.requestAnimationFrame(loop);
})();
                
Що таке rAF?

var AXS_MOVE = 0;
var BTN_JUMP = 1;
var BTN_ATK  = 2;
                

function isPressed(value) { return value ? '[X]' : '[ ]'; }
                

function log(gp) {
    logger.innerHTML = [
        isPressed(gp.axes[AXS_MOVE] < -.5)      + ' Left',
        isPressed(gp.axes[AXS_MOVE] >  .5)      + ' Right',
        isPressed(gp.buttons[BTN_JUMP].pressed) + ' Jump',
        isPressed(gp.buttons[BTN_ATK].pressed)  + ' Atk'
    ].join('\n');
}
                

            

Gamepad

Specification
Support
Article
Demo 1
Demo 2
Better to use smth like this

Battery Status

Позволяет получать данные о состоянии батареи устройства

Feature detection


if (navigator.getBattery) {}
                

navigator
    .getBattery()
    .then(initBattery);

function initBattery(battery) {
    console.log(battery);
}
                

battery {
    level          : 0.94
    charging       : false
    chargingTime   : Infinity
    dischargingTime: 11460
}
                

Properties


battery
    .level           // заряд батареи от 0 до 1
    .chagring        // true, если заряжяется
    .chagringTime    // ~время до полной зарядки, сек
    .dischagringTime // ~время до полной разрядки, сек
                

Events


battery
    .onlevelchange
    .onchagringchange
    .onchagringtimechange
    .ondischagringtimechange
                    

<div id="battery-level"></div>
<div id="battery-charging"></div>
                

var level    = document.getElementById('battery-level');
var charging = document.getElementById('battery-charging');
                

navigator
    .getBattery()
    .then(initBattery);

function initBattery(battery) {
    battery.onlevelchange = updateLevel;
    battery.onlevelchange();

    battery.onchargingchange = updateCharging;
    battery.onchargingchange();
}
                

function updateLevel() {
    level.innerHTML = (this.level * 100).toFixed(2) + '%';
}
                

function updateCharging() {
    var color = this.charging ? '#0a0' : '#a00';
    charging.style.background = color;

    var onOff = this.charging ? 'on' : 'off';
    charging.innerHTML = 'Charger is ' + onOff;
}
                

Battery Status

Specification
Support
Demo

Page Visibility

Позволяет определить видима вкладка браузера или нет

Feature detection


var hidden           = null;
var visibilityState  = null;
var visibilityChange = null;
                

Feature detection


if ('hidden' in document) {
    hidden           = 'hidden';
    visibilityState  = 'visibilityState';
    visibilityChange = 'visibilitychange';
} else if ('mozHidden' in document) {
    hidden           = 'mozHidden';
    visibilityState  = 'mozVisibilityState';
    visibilityChange = 'mozvisibilitychange';
} else if ('webkitHidden' in document) {
    hidden           = 'webkitHidden';
    visibilityState  = 'webkitVisibilityState';
    visibilityChange = 'webkitvisibilitychange';
}
                

Properties


document[hidden]
// true - неактивная вкладка, окно не в фокусе или свернуто
                

document[visibilityState]
// 'visible'   – значение видимой/активной вкладки
// 'hidden'    - значение скрытой вкладки или
//               неактивного/свернутого окна браузера
//
// Необязательные к поддержке значения:
// 'unloaded'  - значение вкладки, которую хотят
//               закрыть/перейти на другую страницу
// 'prerender' - значение пререндереной вкладки
                
Подробнее о "магическом" пререндере

Event


document.addEventListener(visibilityChange, function () {
    console.log([
        '----------------',
        'Hidden: ' + document[hidden],
        'State : ' + document[visibilityState],
        '----------------'
    ].join('\n'));
});
                

Page Visibility

Specification
Support
Article
Demo 1
Demo 2

Web Notifications

Позволяет сообщать пользователю что-либо
вне страницы с помощью карточек-оповещений

Feature detection


var Notification = window.Notification     ||
                   window.webkitNotification;
                
and then...

Notification.requestPermission(callback);
                

Params


new Notification(title, options);
                

title   = 'Hi';        // обязательный параметр
options = {
    body: 'My name is',
    tag : 'SlimShady', // своеобразный id
    dir : 'ltr',       // или 'rtl'
    lang: 'en-US',
    icon: 'img/eminem.jpg'
}
                

Events


var notification = new Notification(title);
                

notification
    .onclick  // при клике на оповещение
    .onclose  // при закрытии, в т.ч. браузером
    .onshow   // при появлении оповещения
    .onerror  // при ошибке, чаще всего, если
              // пользователь запретил оповещения
                

Итого


var notification = new Notification('Hi', {
    body: 'My name is',
    icon: 'img/eminem.jpg',
});

notification.onerror = function () {
    alert('Probably, blocked :\'C');
}
                
Let's try!

Настройки оповещений

Настройки

Дополнительные настройки

Личные Данные

Настройки Контента

Оповещения

Настроить исключения

Web Notifications

Specification
Support
Article
Demo

Vibration

Позволяет управлять вибромотором устройства

Feature detection


var vibrate = navigator.vibrate     ||
              navigator.mozVibrate  ||
              navigator.webkitVibrate;
                

// вибрация длительностью 500ms
vibrate(500); // === [500]
                

// 500ms вибрация, 250ms пауза, 500ms вибрация
vibrate([500, 250, 500]);
                

// останавливает вибрацию
vibrate(0);   // === []
                
Вибрация не блокирует поток выполнения

Vibration

Specification
Support
Article
Demo

That's all folks!