Your SlideShare is downloading. ×
0
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Javascript for mobile devices
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Javascript for mobile devices

2,459

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,459
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
19
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. JS в мобильных устройствах На примере одного проекта
  • 2. ПредставлюсьЮрий Хрусталев, инженер в DataArtyuri.khrustalev@dataart.comhttp://about.me/ykhrustalevhttp://dataart.com
  • 3. Проект• Задача o R&D / Поиск истины – Пригоден ли html5 для использования на мобильных устройствах – UI фреймворк для сайтов заказчика o Сделать демо новостного сайта• Требования o Поддержка наибольшего числа устройств o Простота o Гибкость
  • 4. Все уже сделано, но не нами http://ft.com*источник http://aspirelondon.com/blog/articles/financial-times-app/ft-ipad-app/
  • 5. Чем пользуются в mobile web?• Мобильный телефон• Планшетный компьютер• Читалка• Плеер
  • 6. Через что смотрят mobile web? Webkit браузеры доминируют*источник: http://en.wikipedia.org/wiki/Mobile_operating_system
  • 7. Типичные характеристики• Устройство o Слабая батарейка o Не всегда много памяти o Дорогой интернет (спорно) o Размер экрана в среднем меньше десктопа• Браузер o Ограничен в памяти o Получает системные события не первый o Частично поддерживает новые стандарты
  • 8. Мобильный браузер• Dom API• Хранилище на стороне клиента• Анимация• Аудио, Видео• Canvas• SVG• WebSocket• WebWorkers• ...
  • 9. Проверка возможностейhttp://html5test.com/http://haz.io/http://caniuse.com/
  • 10. Требования к демо сайту• Мокапы o Много картинок в интерфейсе (20 x 10) o Много видео o Все скролится (10 скролов) o Кругом одни слайдшоу (20 слайд шоу)• Дополнительно o Оффлайн режим o Бекэнд постоянно падает o Закладываться на новые устройства
  • 11. Выбор каркаса фреймворка• jquery / jquery mobile o Компоненты – плагины o Нет каркасности• sencha touch / kendo o Есть все (почти) o Лицензия• Backbone o Только MVC o Ничего не навязывает o Нет UI компонентов
  • 12. Слайдеры и скролеры• iScroll• TouchScroll• Wipetouch• Touchswipe• Scrollability• touch-scroll• Zynga Scroller• -webkit-overflow-scrolling:touch;
  • 13. Пишем свой фремворк• Быстрый• Потребляет мало памяти• Кросс браузерный• Гибкий• Слабо связанный
  • 14. Что мы хотели
  • 15. JS рутина• DOM o Селекторы• Array o delete arr[0] o Фильтрация• Object o Итерирование o Наследование• События• Логирование
  • 16. DOM• Jquery o Большой o Известный o Кросбраузерный• Zepto o Легкий o Ориентирован на mobile
  • 17. DOM• css3 селекторы o querySelector() o querySelectorAll()• fragments var 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) ); }
  • 18. Утилиты• Underscore o Легкий o Но только хелперы• Backbone – Коллекции – Диспетчер событий – Модели – Представления – Контроллеры
  • 19. Необходимо невелировать среду• Поддержка ECMA5• CSS• Анимация• Системные события
  • 20. Патерны: Singletonvar instance = (function () { var privateVar; function privateMethod() { // ... } return { // public interface publicMethod: function () { // private members can beaccessed here } };})();
  • 21. Паттерны: Mixin, Inheritance• Прототип o Динамическое изменение поведения всех объектов o Конструктор• Примесь o Копирование поведения
  • 22. Определяем среду исполненияvar ua =navigator.userAgent.toLowerCase().replace(/(.*?)/g, "");var devices = { "android": /androids+([d.]+)/, "opera" : /opera.+(presto/[^.]+.[^.]+)/, "ipad" : /ipad.*oss([d_]+)/, "kindle" : /kindle|silk/};for(i in devices) { if (devices.hasOwnProperty(i)) { var matches = devices[i].test(ua); // .. }}
  • 23. 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;
  • 24. Паттерны: Abstract Factoryvar device = ipad; // androidvar Environment = (function(device) { var environment; switch(device) { case ipad : environment = ... break; ... } environment = _({}).defaults(environment); return { factory : function() { return environment; } }})(device);var environment = Environment.factory();
  • 25. Дебаг и логирование• "use strict" o Подсветка в IDE• Профилирование важно o Замена дебагеру o Поиск узких мест• console.log() o В ipad консоль не раскрывает объекты o Снижает производительность o Не так удобно как хотелось бы
  • 26. Профайлер• Идея log4j o Каждый компонент пишет в своем namespace o Уровни логов (debug, info, warn)• Общий пул сообщений o warn в одном месте может показать состояние всей системы o Альтернатива стек трейсу• Возможность выключить все логи• Возможность смотреть логи в production
  • 27. События приложения• Приложение event-driven• Компоненты знают мало друг о друге• Многие вещи происходят асинхронно o Ajax o Анимация o DOM изменения• События управляют объектами
  • 28. Диспетчер событий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); }); } }};
  • 29. Анимация• translate• translate3d• scale• rotate• Хардварная• CSS префикс• Скорость может отличаться
  • 30. Анимация в деталях• 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);
  • 31. Скорость анимации• Не грузите контент• Не меняйте DOM• Избегайте любых действий во время анимации• translate3d работает только на видимых обхектах• Меняйте DOM только после остановки анимации• Много анимации может привести к падению браузера
  • 32. Скрол• Хуки в процесс анимации• Управление touch событиями• Управление через его API• Синхронизация с другими компонентами• Ускорение• Обработка смены ориентации экрана• Отзывчивый интерфейс
  • 33. Слайдшоу• Ленивое построение слайдов• Экономия памяти• Хуки в процесс анимации• Автослайдинг• Переход на произвольный слайд• Отзывчивый итерфейс
  • 34. Особенности на устройствах• Ipad баг: событие окончания анимации пропускается в ~20% случаев o использовать планировщик• Android при разворотах кидает и "resize" и "orientationchange" o Отлавливать оба события• Android работает медленнее с translate3d при включенном "OpenGL acceleration" o Android WebView
  • 35. Особенности на устройствах• Контейнер не отпускает "move” при выпадении из поля видимости – Прокси для touch событий• Изменение ориентации приводит к перерисовке интерфейса – Быть готовым и обрабатывать корректно• Синхронизация анимации при новых касания – Уметь останавливать анимацию и начинать новую
  • 36. Смена ориентацииwindow.addEventListener(orientationchange, function() { var d = Math.abs(window.orientation); if (d == 90) { // пейзаж } else { // портрет }}, false);• На Android событие resize
  • 37. Планировщик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(); } } }};
  • 38. Синхронизация анимации• Автослайдинг Proxy контейнер для делегирования событий на активный слайд Visible Screen Scrollable Y Scrollable Y Slide Slide 1 2
  • 39. Синхронизация анимации• Текущее положение анимируемого контейнераvar computedStyle = window.getComputedStyle(node)[-webkit-transform];var parsedMatrix = new WebKitCSSMatrix(computedStyle);var x = parsedMatrix.e;var y = parsedMatrix.f;• При смене ориентации необходимо пересчитывать размеры
  • 40. Навигация в приложении• Url fragment # o http://app.example.com#account o http://app.example.com#news• Подписка событий на изменение url window.addEventListener("hashchange", function () { var router = window.location.hash; // ... }); function navigate(route) { window.location.hash = route; }• Изменение hash медленная операция
  • 41. Хранилище на стороне клиента• до 50 мб (требует подтверждения пользователя)• Local storage• App cache• Indexed DB• Websql (не является стандартом)• Cookies
  • 42. Хранилище на стороне клиента• local storage localStorage.key = value• app cache <html manifest="app.appcache"> #app.appcache CACHE MANIFEST index.html css/main.css js/app.js
  • 43. Обновления• Обновление файлов из манифеста var cache = window["applicationCache"]; cache.addEventListener(updateready, function () { window.location.reload(); });• Чистка локального хранилища localStorage.clear();• Получение свежих файлов o запросить http://app.example.com/file?{timestamp}
  • 44. Аудио, Видео• тег video• <video controls autoplay preload src="video.mp4"></video> тег audio <audio controls autoplay preload loop src="audio.wav">• Формат у всех свой• Процессор у всех разный• Спеки лучший друг• Готовим контент на сервере
  • 45. Шаблоны• Обрабатываются на клиенте• Удобные для верстки• Понятные для браузера• Быстрые в обработке• XSS
  • 46. Шаблонизаторы• Mustache – язык шаблонов• Реализация • dust.js • hogan.js• Серверный компилятор o node.js
  • 47. Компиляция шаблонов• Сервер <ul> {#messages} <li data-id="{id}">{text}</li> {/messages} </ul> o Распарсить шаблон o Скомпилировать в JS представление• Клиент o Вставить данные o Обновить html• Внутренне представление шаблона o Конкатенация JS строк
  • 48. Отрисовка HTML• Работа с DOM может быть дорогой o Reflow – пересчет параметров дерева o Repaint – перерисовка старницы• Как избежать o Fragments o Большие части лучше менять innerHtml o Маленькие изменения напрямую через DOM
  • 49. Собираем все вместе• Браузер загружает файлы асинхронно• Велика вероятность конфликта зависимостей• Глобальная область видимости• Модульная архитектура• Выход есть o Инъекция зависиммостей o Компиляция всего приложения
  • 50. Require.js• Поддерживает минификацию o JS o CSS• Умеет грузить файлы по порядку• Помогает избегать конфликтов имен• Работает с node.js
  • 51. Require.js<!DOCTYPE html><html manifest="app.minifest"> <head></head> <body> <script src="js/require.js" data-main="js/application"></script> </body></html>
  • 52. Require.js// spec.jsrequire.config({ paths: { "zepto": "vendor/zepto", "logger": "lib/logger", "environment": "lib/environment", ... }});
  • 53. Require.js// application.jsdefine([ "order!zepto", // соблюдает порядок "logger"], function ($, Logger) { var logger = new Logger; // ...});
  • 54. Производительность• Профилирование• Быстрые операции o Математические расчеты o Запросы к DOM o Оперирование объектами• Медленные операции o Изменения в DOM o Отрисовка• Компиляция шаблонов• Минификация CSS, JS• Освобождение ресурсов
  • 55. Память• Потребители памяти – Картинки – DOM дерево – Анимация• Если память кончится, браузер упадет• Меры борьбы – Прятать все, что не видно пользователю – Используем бекграундные картинки вместо <img> – Избегать reflow/repaint, особенно при анимации – Избавляться от тяжелых библиотек
  • 56. Интеграция с бекэндом• Минимизируем число http запросов o Запрос всех картинок одним запросом o Кодирование картинок в base 64• JSON/ GZIP• Подготовка контента o Изменение размеров картинок под устройство• Application cache• Чем меньше логики на клиенте - тем лучше
  • 57. Делаем свою Карусель
  • 58. Требования• Карусель картинок• Работоспособность в ipad, chrome• Поддержка событий мышки• Режим слайдшоу• Плавная анимация
  • 59. Контейнеры• Прокрутка осуществляется на контейнере, содержащем слайды• Показываем только видимые элементы• Контейнеры вне зоны видимости скрываем для экономии ресурсов
  • 60. Следим за браузером• touchStart - один раз• touchMove - много раз• touchEnd - один раз• transitionEnd – по окончании анимации• resize/orientationchange - смена ориентации• Не забываем про разницу chrome и ipad o В chrome перенос мышки на новую позицию вызывает "move"
  • 61. API• setSlideShowState(state)• moveNext()• movePrevious()• reset()
  • 62. Запрещаем zoom<meta name="viewport" content="width=device-width, initial-scale=1, maximum- scale=1, minimum-scale=1, user-scalable=no"/>
  • 63. Конструктор• Параметры по умолчанию• Навешивает DOM события• Делает все расчеты позиционирования o Окна просмотра o Слайдов• Сохраняет ссылки на слайды
  • 64. Обработчик браузерных событий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; }}
  • 65. Алгоритм слайдинга• Вылавливае "start"• Запоминаем начальную точку• Следим за событием "move"• Передвигаем контейнер слайдов• По событию "end" проверяем нужно ли осуществить полный слайд или вернуть в исходное положение• Блокируем объект до окончания анимации
  • 66. Алгоритм слайдшоу• Создаем вызов для слайдинга• В момент исполнения вызова проверяем состояние слайдшоу (true/false) o true - moveNext() o false - ничего o В момент анимации блокируем объект• При достижении границы переходим на первый слайд
  • 67. Узкие места• Потеря состояния начала движения• Потеря события "transitionEnd" (ipad bug)• Некорректная обработка смены ориентации
  • 68. КонтактыЮрий Хрусталев, инженер в DataArtyuri.khrustalev@dataart.comhttp://about.me/ykhrustalev

×