68
JS в мобильных устройствах На примере одного проекта

Javascript for mobile devices

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Javascript for mobile devices

JS в мобильных устройствахНа примере одного проекта

Page 2: Javascript for mobile devices

Представлюсь

Юрий Хрусталев, инженер в [email protected]://about.me/ykhrustalev

http://dataart.com

Page 3: Javascript for mobile devices

Проект

• Задача o R&D / Поиск истины– Пригоден ли html5 для использования на

мобильных устройствах– UI фреймворк для сайтов заказчикаo Сделать демо новостного сайта

• Требованияo Поддержка наибольшего числа устройствo Простотаo Гибкость

Page 4: Javascript for mobile devices

Все уже сделано, но не нами

*источник http://aspirelondon.com/blog/articles/financial-times-app/ft-ipad-app/

http://ft.com

Page 5: Javascript for mobile devices

Чем пользуются в mobile web?

• Мобильный телефон

• Планшетный компьютер

• Читалка

• Плеер

Page 6: Javascript for mobile devices

*источник: http://en.wikipedia.org/wiki/Mobile_operating_system

Через что смотрят mobile web?

Webkit браузеры доминируют

Page 7: Javascript for mobile devices

Типичные характеристики

• Устройствоo Слабая батарейкаo Не всегда много памятиo Дорогой интернет (спорно)o Размер экрана в среднем меньше десктопа

• Браузер o Ограничен в памятиo Получает системные события не первыйo Частично поддерживает новые стандарты

Page 8: Javascript for mobile devices

Мобильный браузер

• Dom API

• Хранилище на стороне клиента

• Анимация

• Аудио, Видео

• Canvas

• SVG

• WebSocket

• WebWorkers

• ...

Page 9: Javascript for mobile devices

Проверка возможностей

http://html5test.com/http://haz.io/http://caniuse.com/

Page 10: Javascript for mobile devices

Требования к демо сайту

• Мокапыo Много картинок в интерфейсе (20 x 10)o Много видеоo Все скролится (10 скролов)o Кругом одни слайдшоу (20 слайд шоу)

• Дополнительноo Оффлайн режимo Бекэнд постоянно падаетo Закладываться на новые устройства

Page 11: Javascript for mobile devices

Выбор каркаса фреймворка

• jquery / jquery mobileo Компоненты – плагиныo Нет каркасности

• sencha touch / kendoo Есть все (почти)o Лицензия

• Backboneo Только MVCo Ничего не навязываетo Нет UI компонентов

Page 12: Javascript for mobile devices

Слайдеры и скролеры

• iScroll

• TouchScroll

• Wipetouch

• Touchswipe

• Scrollability

• touch-scroll

• Zynga Scroller

• -webkit-overflow-scrolling:touch;

Page 13: Javascript for mobile devices

Пишем свой фремворк

• Быстрый

• Потребляет мало памяти

• Кросс браузерный

• Гибкий

• Слабо связанный

Page 14: Javascript for mobile devices

Что мы хотели

Page 15: Javascript for mobile devices

JS рутина

• DOMo Селекторы

• Array o delete arr[0]o Фильтрация

• Objecto Итерированиеo Наследование

• События

• Логирование

Page 16: Javascript for mobile devices

DOM

• Jqueryo Большойo Известныйo Кросбраузерный

• Zeptoo Легкийo Ориентирован на mobile

Page 17: Javascript for mobile devices

DOM

• css3 селекторыo querySelector()o querySelectorAll()

• fragmentsvar div = document.getElementsByTagName("div");

var fragment = document.createDocumentFragment();

for ( var e = 0; e < elems.length; e++ ) {

fragment.appendChild( elems[e] );

}

for ( var i = 0; i < div.length; i++ ) {

div[i].appendChild( fragment.cloneNode(true) );

}

Page 18: Javascript for mobile devices

Утилиты

• Underscoreo Легкийo Но только хелперы

• Backbone– Коллекции– Диспетчер событий– Модели– Представления– Контроллеры

Page 19: Javascript for mobile devices

Необходимо невелировать среду

• Поддержка ECMA5

• CSS

• Анимация

• Системные события

Page 20: Javascript for mobile devices

Патерны: Singleton

var instance = (function () { var privateVar; function privateMethod() { // ... } return { // public interface publicMethod: function () { // private members can be accessed here } };})();

Page 21: Javascript for mobile devices

Паттерны: Mixin, Inheritance

• Прототипo Динамическое изменение поведения всех

объектовo Конструктор

• Примесьo Копирование поведения

Page 22: Javascript for mobile devices

Определяем среду исполнения

var ua = navigator.userAgent.toLowerCase().replace(/\(.*?\)/g, "");var devices = { "android": /android\s+([\d.]+)/, "opera" : /opera.+(presto\/[^.]+\.[^.]+)/, "ipad" : /ipad.*os\s([\d_]+)/, "kindle" : /kindle|silk/};

for(i in devices) { if (devices.hasOwnProperty(i)) { var matches = devices[i].test(ua); // .. }}

Page 23: Javascript for mobile devices

Touch события

var hasTouch = 'ontouchstart' in window;

var Events = { hasTouch : hasTouch, resizeEvent : ('onorientationchange' in window ) ? 'orientationchange' : 'resize', clickEvent : hasTouch ? 'tap' : 'click', // синтетическое startEvent : hasTouch ? 'touchstart' : 'mousedown', // один раз moveEvent : hasTouch ? 'touchmove' : 'mousemove', // постоянно endEvent : hasTouch ? 'touchend' : 'mouseup', // один раз cancelEvent : hasTouch ? 'touchcancel' : 'mouseup',};

// webkitEvents.transitionEndEvent = 'webkitTransitionEnd';

Page 24: Javascript for mobile devices

Паттерны: Abstract Factory

var device = 'ipad'; // 'android'

var Environment = (function(device) { var environment;

switch(device) { case 'ipad' : environment = ... break; ... } environment = _({}).defaults(environment); return { factory : function() { return environment; } }})(device);

var environment = Environment.factory();

Page 25: Javascript for mobile devices

Дебаг и логирование

• "use strict" o Подсветка в IDE

• Профилирование важноo Замена дебагеруo Поиск узких мест

• console.log()o В ipad консоль не раскрывает объектыo Снижает производительностьo Не так удобно как хотелось бы

Page 26: Javascript for mobile devices

Профайлер

• Идея log4jo Каждый компонент пишет в своем namespaceo Уровни логов (debug, info, warn)

• Общий пул сообщенийo warn в одном месте может показать состояние

всей системы o Альтернатива стек трейсу

• Возможность выключить все логи

• Возможность смотреть логи в production

Page 27: Javascript for mobile devices

События приложения

• Приложение event-driven

• Компоненты знают мало друг о друге

• Многие вещи происходят асинхронноo Ajaxo Анимацияo DOM изменения

• События управляют объектами

Page 28: Javascript for mobile devices

Диспетчер событий

function EventDispatcher() { this._events = {};}

EventDispatcher.prototype = { on: function (name, handler, scope) { this._events[name] = this._events[name] || []; this._events[name].push({ handler: handler, scope: scope || this }); },

fire: function (name) { var args = arguments.toArray().slice(1), events = this._events[name]; if (events) { events.forEach(function (event) { event.handler.apply(event.scope, args); }); } }};

Page 29: Javascript for mobile devices

Анимация

• translate

• translate3d

• scale

• rotate

• Хардварная

• CSS префикс

• Скорость может отличаться

Page 30: Javascript for mobile devices

Анимация в деталях

• CSS .container { -webkit-transform: translate3d(0px, -700px, 0px); -webkit-transition: all 10s cubic-bezier(0, 0, 0.1, 1); -webkit-transform-style: preserve-3d;

}

• Jquery/Zepto$('.container').animate({ 'translate3d': 'translate3d(0px, -700px, 0px)',}, 10);

Page 31: Javascript for mobile devices

Скорость анимации

• Не грузите контент

• Не меняйте DOM

• Избегайте любых действий во время анимации

• translate3d работает только на видимых обхектах

• Меняйте DOM только после остановки анимации

• Много анимации может привести к падению браузера

Page 32: Javascript for mobile devices

Скрол

• Хуки в процесс анимации

• Управление touch событиями

• Управление через его API

• Синхронизация с другими компонентами

• Ускорение

• Обработка смены ориентации экрана

• Отзывчивый интерфейс

Page 33: Javascript for mobile devices

Слайдшоу

• Ленивое построение слайдов

• Экономия памяти

• Хуки в процесс анимации

• Автослайдинг

• Переход на произвольный слайд

• Отзывчивый итерфейс

Page 34: Javascript for mobile devices

Особенности на устройствах

• Ipad баг: событие окончания анимации пропускается в ~20% случаевo использовать планировщик

• Android при разворотах кидает и "resize" и "orientationchange"o Отлавливать оба события

• Android работает медленнее с translate3d при включенном "OpenGL acceleration"o Android WebView

Page 35: Javascript for mobile devices

Особенности на устройствах

• Контейнер не отпускает "move” при выпадении из поля видимости– Прокси для touch событий

• Изменение ориентации приводит к перерисовке интерфейса – Быть готовым и обрабатывать корректно

• Синхронизация анимации при новых касания – Уметь останавливать анимацию и начинать

новую

Page 36: Javascript for mobile devices

Смена ориентации

window.addEventListener('orientationchange', function() { var d = Math.abs(window.orientation);

if (d == 90) {

// пейзаж } else { // портрет }}, false);

• На Android событие 'resize'

Page 37: Javascript for mobile devices

Планировщик

var Scheduler = function () { this.callbacks = []; this.timers = [];};

Scheduler.prototype = { schedule: function (callback, delay) { var self = this; self.callbacks.push(callback); var timer = setTimeout(function () { self.execute(); }, delay); self.timers.push(timer); },

execute: function () { var callbacks = this.callbacks; if (callbacks && callbacks.length) { var cb; while (cb = callbacks.shift()) { cb(); } } }};

Page 38: Javascript for mobile devices

Синхронизация анимации

• Автослайдинг

Visible Screen

Scrollable YSlide 1

Scrollable Y Slide 2

Proxy контейнер для делегирования событий на активный слайд

Page 39: Javascript for mobile devices

Синхронизация анимации

• Текущее положение анимируемого контейнера

var computedStyle = window.getComputedStyle(node)['-webkit-transform']; var parsedMatrix = new WebKitCSSMatrix(computedStyle); var x = parsedMatrix.e; var y = parsedMatrix.f;

• При смене ориентации необходимо пересчитывать размеры

Page 40: Javascript for mobile devices

Навигация в приложении

• Url fragment #o http://app.example.com#accounto http://app.example.com#news

• Подписка событий на изменение urlwindow.addEventListener("hashchange", function () { var router = window.location.hash; // ...});

function navigate(route) { window.location.hash = route;}

• Изменение hash медленная операция

Page 41: Javascript for mobile devices

Хранилище на стороне клиента

• до 50 мб (требует подтверждения пользователя)

• Local storage

• App cache

• Indexed DB

• Websql (не является стандартом)

• Cookies

Page 42: Javascript for mobile devices

Хранилище на стороне клиента

• local storagelocalStorage.key = 'value'

• app cache<html manifest="app.appcache">

#app.appcache

CACHE MANIFEST

index.html

css/main.css

js/app.js

Page 43: Javascript for mobile devices

Обновления

• Обновление файлов из манифестаvar cache = window["applicationCache"];cache.addEventListener('updateready', function () { window.location.reload();

});

• Чистка локального хранилищаlocalStorage.clear();

• Получение свежих файловo запросить http://app.example.com/file?

{timestamp}

Page 44: Javascript for mobile devices

Аудио, Видео

• тег video <video controls autoplay preload src="video.mp4"></video>

• тег audio <audio controls autoplay preload loop src="audio.wav">

• Формат у всех свой

• Процессор у всех разный

• Спеки лучший друг

• Готовим контент на сервере

Page 45: Javascript for mobile devices

Шаблоны

• Обрабатываются на клиенте

• Удобные для верстки

• Понятные для браузера

• Быстрые в обработке

• XSS

Page 46: Javascript for mobile devices

Шаблонизаторы

• Mustache – язык шаблонов

• Реализация• dust.js

• hogan.js

• Серверный компиляторo node.js

Page 47: Javascript for mobile devices

Компиляция шаблонов

• Сервер<ul>

{#messages}

<li data-id="{id}">{text}</li>

{/messages}

</ul>

o Распарсить шаблонo Скомпилировать в JS представление

• Клиентo Вставить данныеo Обновить html

• Внутренне представление шаблонаo Конкатенация JS строк

Page 48: Javascript for mobile devices

Отрисовка HTML

• Работа с DOM может быть дорогойo Reflow – пересчет параметров дереваo Repaint – перерисовка старницы

• Как избежатьo Fragmentso Большие части лучше менять innerHtmlo Маленькие изменения напрямую через DOM

Page 49: Javascript for mobile devices

Собираем все вместе

• Браузер загружает файлы асинхронно

• Велика вероятность конфликта зависимостей

• Глобальная область видимости

• Модульная архитектура

• Выход естьo Инъекция зависиммостейo Компиляция всего приложения

Page 50: Javascript for mobile devices

Require.js

• Поддерживает минификациюo JSo CSS

• Умеет грузить файлы по порядку

• Помогает избегать конфликтов имен

• Работает с node.js

Page 51: Javascript for mobile devices

Require.js

<!DOCTYPE html><html manifest="app.minifest"> <head></head> <body> <script src="js/require.js" data-main="js/application"></script> </body></html>

Page 52: Javascript for mobile devices

Require.js

// spec.jsrequire.config({ paths: { "zepto": "vendor/zepto", "logger": "lib/logger", "environment": "lib/environment", ... }});

Page 53: Javascript for mobile devices

Require.js

// application.jsdefine([ "order!zepto", // соблюдает порядок "logger"], function ($, Logger) { var logger = new Logger; // ...});

Page 54: Javascript for mobile devices

Производительность

• Профилирование

• Быстрые операцииo Математические расчетыo Запросы к DOMo Оперирование объектами

• Медленные операцииo Изменения в DOMo Отрисовка

• Компиляция шаблонов

• Минификация CSS, JS

• Освобождение ресурсов

Page 55: Javascript for mobile devices

Память

• Потребители памяти– Картинки– DOM дерево– Анимация

• Если память кончится, браузер упадет• Меры борьбы– Прятать все, что не видно пользователю– Используем бекграундные картинки вместо <img>– Избегать reflow/repaint, особенно при анимации– Избавляться от тяжелых библиотек

Page 56: Javascript for mobile devices

Интеграция с бекэндом

• Минимизируем число http запросовo Запрос всех картинок одним запросомo Кодирование картинок в base 64

• JSON/ GZIP

• Подготовка контентаo Изменение размеров картинок под устройство

• Application cache

• Чем меньше логики на клиенте - тем лучше

Page 57: Javascript for mobile devices

Делаем свою Карусель

Page 58: Javascript for mobile devices

Требования

• Карусель картинок

• Работоспособность в ipad, chrome

• Поддержка событий мышки

• Режим слайдшоу

• Плавная анимация

Page 59: Javascript for mobile devices

Контейнеры

• Прокрутка осуществляется на контейнере, содержащем слайды

• Показываем только видимые элементы• Контейнеры вне зоны видимости скрываем для

экономии ресурсов

Page 60: Javascript for mobile devices

Следим за браузером

• touchStart - один раз

• touchMove - много раз

• touchEnd - один раз

• transitionEnd – по окончании анимации

• resize/orientationchange - смена ориентации

• Не забываем про разницу chrome и ipado В chrome перенос мышки на новую позицию

вызывает "move"

Page 61: Javascript for mobile devices

API

• setSlideShowState(state)

• moveNext()

• movePrevious()

• reset()

Page 62: Javascript for mobile devices

Запрещаем zoom

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,

minimum-scale=1, user-scalable=no"/>

Page 63: Javascript for mobile devices

Конструктор

• Параметры по умолчанию

• Навешивает DOM события

• Делает все расчеты позиционированияo Окна просмотраo Слайдов

• Сохраняет ссылки на слайды

Page 64: Javascript for mobile devices

Обработчик браузерных событий

Scroll.prototype = { handleEvent: function (e) { switch (e.type) { case startEvent: this._startTouch(e); break; case moveEvent: this._moveTouch(e); break; case endEvent: this._endTouch(e); break; case resizeEvent: this._resize(e); break; case transitionEndEvent: this._transitionEnd(e); break; } return false; }}

Page 65: Javascript for mobile devices

Алгоритм слайдинга

• Вылавливае "start"

• Запоминаем начальную точку

• Следим за событием "move"

• Передвигаем контейнер слайдов

• По событию "end" проверяем нужно ли осуществить полный слайд или вернуть в исходное положение

• Блокируем объект до окончания анимации

Page 66: Javascript for mobile devices

Алгоритм слайдшоу

• Создаем вызов для слайдинга

• В момент исполнения вызова проверяем состояние слайдшоу (true/false)o true - moveNext()o false - ничегоo В момент анимации блокируем объект

• При достижении границы переходим на первый слайд

Page 67: Javascript for mobile devices

Узкие места

• Потеря состояния начала движения

• Потеря события "transitionEnd" (ipad bug)

• Некорректная обработка смены ориентации

Page 68: Javascript for mobile devices

Контакты

Юрий Хрусталев, инженер в [email protected]://about.me/ykhrustalev