"favicon на стероидах" Александр Амосов (avito)
TRANSCRIPT
Favicon на стероидахАмосов Александр, AVITO
email: [email protected] twitter: @gc_s9k
Задача
2
• Messenger для обмена сообщениями между продавцом и покупателем
• Привлечь внимание пользователя, когда приходит новое сообщение
Задача1. Отображать favicon с количеством
непрочитанных сообщений
3
Задача1. Отображать favicon с количеством
непрочитанных сообщений
2. Не отображать favicon на активной вкладке
4
Задача1. Отображать favicon с количеством
непрочитанных сообщений
2. Не отображать favicon на активной вкладке
3. Favicon должен мигать
5
• Создать заранее все картинки
• Создавать динамически с помощью canvas
Отрисовка favicon
6
1 2 3 …
Отрисовка faviconconst canvas = document.createElement('canvas'); canvas.width = SIZE; canvas.height = SIZE; const context = canvas.getContext('2d');
Создаем canvas и получаем 2d контекст
7
Отрисовка faviconconst canvas = document.createElement('canvas'); canvas.width = SIZE; canvas.height = SIZE; const context = canvas.getContext('2d');
context.fillStyle = '#ff6163'; context.beginPath(); context.arc(SIZE / 2, SIZE / 2, SIZE / 2, 0, 2 * Math.PI); context.fill();
8
Отрисовка faviconconst canvas = document.createElement('canvas'); canvas.width = SIZE; canvas.height = SIZE; const context = canvas.getContext('2d');
context.fillStyle = '#ff6163'; context.beginPath(); context.arc(SIZE / 2, SIZE / 2, SIZE / 2, 0, 2 * Math.PI); context.fill();
context.fillStyle = 'white'; context.font = `${fontSize}px Arial`; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillText(number, SIZE / 2, SIZE / 2);
2
9
Отрисовка faviconconst iconNode = document.createElement('link'); iconNode.rel = 'icon'; iconNode.type = 'image/png'; iconNode.href = canvas.toDataURL('image/png');
document.head.appendChild(iconNode);
Создаем элемент иконки и добавляем в head
10
Отрисовка favicon
11
IE и Edge
12
• Не работают base64 фавиконки
• Не работает смена фавиконок
Задача1. Отображать favicon с количеством
непрочитанных сообщений
2. Не отображать favicon на активной вкладке
3. Favicon должен мигать
13
Visibility API
14
15
document.addEventListener('visibilitychange', () => { const isVisible = !document.hidden; // ... });
Visibility API
16
Задача1. Отображать favicon с количеством
непрочитанных сообщений
2. Не отображать favicon на активной вкладке
3. Favicon должен мигать
17
Мигание• setInterval
18
Мигание• setInterval
19
Мигание• setInterval
• gif?
20
Мигание• setInterval
• gif
• Web Worker
21
Web Worker• Выполняются в отдельном потоке
• Код находится в отдельном файле
• Нельзя манипулировать DOM
• Нет requestAnimationFrame
• Общение через сообщения
• Имеют свой глобальный объект
22
Доступно• Объект navigator, location
• Fetch / XMLHttpRequest / WebSocket
• setTimeout()/clearTimeout() и setInterval()/clearInterval()
• IndexedDB
• Создание других Web Worker’ов
23
Обмен сообщениями• Простые типы данных
24
Примерconst worker = new Worker('worker.js'); worker.postMessage('request'); worker.onmessage = ({ data }) => { console.log(data); };
onmessage = ({ data }) => { console.log(data); postMessage('answer'); };
worker.jsmain.js
25
Обмен сообщениями• Простые типы данных
• Объекты
26
Пример
onmessage = ({ data }) => { console.log(data); postMessage('answer'); };
worker.jsmain.js
const worker = new Worker('worker.js'); worker.postMessage({ arr: [2, 3] }); worker.onmessage = ({ data }) => { console.log(data); };
27
Обмен сообщениями• Простые типы данных
• Объекты
• Transferrable objects
28
worker.jsmain.js
const typedArray = new Uint8Array([0, 1, 2]);
const worker = new Worker('worker.js'); worker.postMessage(typedArray, [typedArray.buffer]);
worker.onmessage = ({ data }) => { console.log(data); };
onmessage = ({ data: typedArray }) => { postMessage(typedArray, [typedArray.buffer]); };
29
Применение• Для обработки больших объемов данных в отдельном потоке
• обработка текста
• обработка изображений, видео, аудио
• обработка данных после получения через ajax
• расчет физики в играх
30
Применение• Для обработки больших объемов данных в отдельном потоке
• обработка текста
• обработка изображений, видео, аудио
• обработка данных после получения через ajax
• расчет физики в играх
• Для использования intervals/timeouts без ограничений
31
let intervalId; const INTERVAL_TIME = 2000;
onmessage = function({ data }) { switch (data) { case 'start': clearInterval(intervalId);
intervalId = setInterval(() => { postMessage('tick'); }, INTERVAL_TIME); break;
case 'stop': clearInterval(intervalId); break; } };
32
Web Worker
33
Задача1. Отображать favicon с количеством непрочитанных
сообщений
2. Не отображать favicon на активной вкладке
3. Favicon должен мигать
4. Несколько вкладок должны мигать синхронно O_o
34
Синхронизация• SharedWorker
35
SharedWorker• Может связываться сразу с несколькими контекстами
• Работает пока не закроются все страницы, его использующие
36
worker.jsmain.js
const worker = new SharedWorker('worker.js');
worker.port.postMessage('start'); worker.port.onmessage = ({ data }) => { console.log(data); };
const ports = [];
onconnect = ({ ports: [port] }) => { ports.push(port);
port.onmessage = ({ data }) => { if (data === 'start') { port.postMessage(`connection: ${ports.length}`); } }; };
37
Применение• Расшаренный между вкладками WebSocket
38
39
const ports = []; const INTERVAL_TIME = 2000;
setInterval(() => { ports.forEach(port => { port.postMessage('tick'); }); }, INTERVAL_TIME);
onconnect = (event) => { const port = event.ports[0]; ports.push(port); };
40
Синхронизация• SharedWorker
• Нить времени
41
10:00 10:02 10:04 10:06 10:08 10:10
42
10:00 10:02 10:04 10:06 10:08 10:10
43
10:00 10:02 10:04 10:06 10:08 10:10
44
let timeoutId; const INTERVAL_TIME = 2000;
function tick() { const timeToStart = INTERVAL_TIME - Date.now() % INTERVAL_TIME;
timeoutId = setTimeout(tick, timeToStart); postMessage('tick'); }
onmessage = function({ data }) { switch (data) { case 'start': clearTimeout(timeoutId); tick(); break;
case 'stop': clearTimeout(timeoutId); break; } };
45
10:00 10:02 10:04 10:06 10:08 10:10
2 2
46
Проблемы• В Chrome 54 ограничение на веб воркер в неактивной вкладке
• На каждую вкладку создается свой веб воркер
47
48
49
Shared Worker
Dedicated Worker
setInterval
Задача1. Отображать favicon с количеством непрочитанных
сообщений
2. Не отображать favicon на активной вкладке
3. Favicon должен мигать
4. Несколько вкладок должны мигать синхронно
50
Спасибо! Вопросы?
52
Амосов Александр
email: [email protected] twitter: @gc_s9k
http://bit.ly/timersjs