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

Javascript for mobile devices

Nov 28, 2014

Download

Documents

Yuri Khrustalev

 
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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