Я люблю высокопроизводительный JavaScript, и мне нравится делиться тем, что я считаю его истинным потенциалом. В этом уроке я хочу сфокусироваться на Famo.us, который может позволить вам поддерживать плавную плавную передачу 60 кадров в секунду при плавной анимации на экране.
Famo.us делает это, используя примитив CSS3 -webkit-transform: matrix3d , который позволяет платформе вычислять составную матрицу и пропустить средство визуализации браузера. Нет плагина, нет загрузки, нет взлома. Добавив это к каждому DIV, разработчики могут визуализировать составную матрицу и перейти прямо к графическому процессору.
Я углубляюсь в обсуждение всех подробностей Famo.us в этом посте . Спасибо Заку Брауну за его помощь в этом! Давайте начнем.
К концу этого проекта вы сможете:
- понять, как работает Angular в контексте приложения Famo.us
- использовать истинную силу JavaScript и хорошие части HTML5
- создавать плавные анимации
Моя цель этого проекта — показать, как легко вы можете создавать проекты HTML5 и JavaScript, которые работают на мобильных приложениях с почти естественной скоростью.
Характеристики
- Мобильное приложение работает на iOS и Android через Cordova.
- Универсальное приложение Windows 10 изначально работает на Windows 10.
- Этот проект также может быть запущен как размещенный веб-сайт, хотя у меня есть его масштаб, который лучше всего подходит для мобильных устройств.
Требования
- ПК или Mac
- веб сервер
- Кросс-платформенная тестовая матрица (например, BrowserStack, IDE или бесплатные виртуальные машины для EdgeHTML, механизм рендеринга для Microsoft Edge и размещенный контент веб-приложений в Windows 10)
Настроить
- Загрузите источник с GitHub .
- Загрузите и установите веб-сервер (я использую MAMP на OS X или встроенный сервер IIS с Visual Studio на Windows).
Откройте проект
- Запустите свой веб-сервер.
- Перейдите к известному-angular-Pokemon / app / .
Проект предназначен для работы на мобильных устройствах, поэтому используйте мобильный эмулятор в своем браузере, чтобы получить правильный вид. Вот как это будет выглядеть на iPhone 6 внутри эмулятора с помощью браузера Chrome для настольных ПК (375×667):

Как это устроено
Удар по базе данных
Я извлекаю всю информацию из PokeAPI , который имеет хорошо документированный API, но в нем отсутствуют изображения для каждого покемона. Для изображений я просто вытягиваю имя выбранного в данный момент покемона и добавляю его в конец этого URL: http://img.pokemondb.net/artwork/ . Например: http://img.pokemondb.net/artwork/venusaur.jpg приведет вас к изображению Vanosaur. Отличный, верно? К сожалению, у них нет API.
Каждый раз, когда пользователь нажимает кнопку Next , генерируется случайное число между значением min / max, которое я определил (скажем, от 1 до 20), и он извлекает покемона из базы данных, которая соответствует этому числу. Вот как это выглядит:
http://pokeapi.co/api/v1/pokemon/1/ возвращает объект JSON для Bulbasaur. Вы можете играть с их API .
Цикл данных
Затем я перебираю этот объект JSON и устанавливаю свойства, которые нахожу, переменными в Angular, используя объект $Scope .
Вот пример:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/*
* Grab Pokemon from the DB
*/
$scope.getPokemon = function () {
// Generate a random num and use it for the next pokemon
getRandomInt($scope.minVal, $scope.maxVal);
// Retrieve data from DB and draw it to screen
$http.get($scope.dbURL + $scope.pokemonNum + «/»)
.success(function(data) {
$scope.name = data.name;
$scope.imageUrl = $scope.imgDbURL + $scope.name.toLowerCase() + ‘.jpg’;
/* 1) Empty out the current array to store the new items in there
* 2) Capitalize the first character for each ability from the database
* 3) Store that ability in a new abilityObj & add it into the abilities array
*/
$scope.abilities.length = 0;
for (var i = 0; i < data.abilities.length; i++){
var capitalizedString = capitalizeFirstLetter(data.abilities[i].name);
var abilityObj = {name: capitalizedString };
$scope.abilities.push(abilityObj);
}
$scope.hitPoints = data.
var firstType = data.types[0].name;
$scope.types.name = capitalizeFirstLetter(firstType);
determineNewBgColor();
})
.error(function(status){
console.log(status);
$scope.name = «Couldn’t get Pokemon from the DB»;
});
};
|
Вы можете заметить, что у меня также есть несколько других функций, таких как capitalizeFirstLetter , который делает именно это. Я хотел, чтобы в способностях и типах (например, яд, трава, полет) первая буква была заглавной, поскольку они возвращаются из базы данных всеми строчными буквами.
Я также перебираю способности и помещаю их в объект способности, который выглядит следующим образом:
|
1
2
3
4
|
$scope.abilities = [
{ name: «Sleep»},
{ name: «Eat» }
];
|
База данных также возвращает несколько типов для определенных покемонов, таких как Чаризард, который летит так же, как и огонь. Для простоты я хотел вернуть только один из базы данных.
|
1
2
3
|
$scope.types = { name: «Grass» };
var firstType = data.types[0].name;
|
Рисование на экране
Famo.us имеет две волны рисования контента на экране, создавая поверхности , которые являются элементами, которые содержат ваш текст, изображения и т. Д .:
- JavaScript
- Директивы FA (HTML)
Я не использовал JavaScript для рисования поверхностей в этом приложении. Вместо этого я решил использовать только директивы FA (Famous-Angular), такие как:
|
01
02
03
04
05
06
07
08
09
10
11
|
<!— Name—>
<fa-modifier
fa-origin =»origin.center»
fa-align =»align.frontName»
fa-size =»size.frontName»
fa-translate =»trans.topLayer»>
<fa-surface
class =»front-name-text»>
{{name}}
</fa-surface>
</fa-modifier>
|
Это имя над покемоном на переднем экране.
Вы заметите, что поверхность обернута fa-modifier . Вы можете прочитать о них в документации Famo.us , но они по существу регулируют свойства поверхности, такие как выравнивание, размер и происхождение. Мне потребовалось некоторое время, чтобы обернуть голову в разницу между выравниванием и происхождением, так что вот как я это понял.
происхождения
Это точка отсчета на любой поверхности. Если я хочу нарисовать прямоугольник и переместить его по экрану, мне нужно решить, какая точка на этом прямоугольнике будет моей отправной точкой. Документы Famo.us хорошо это объясняют. Значения выложены следующим образом:
|
1
2
3
4
5
6
7
|
$scope.origin = {
// XY topLeft: [0, 0 ],
topRight: [1, 0 ],
center: [0.5, 0.5],
bottomLeft: [0, 1 ],
bottomRight: [1, 1 ]
};
|
центровка
Это местоположение поверхности на экране. Когда вы вносите изменения в выравнивание, оно использует исходную точку в качестве исходной точки для начала.
|
1
2
3
4
5
6
|
$scope.align = {
// XY frontName: [0.50, 0.10],
frontImg: [0.50, 0.40],
backImg: [0.5, 0.38],
center: [0.50, 0.50]
};
|
Где, наконец, приходит угловой
Теперь вы можете использовать все свои навыки Angular и привязку данных для работы с реализацией Angular. Если вы уже знакомы с Angular, то здесь он не сильно отличается.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<!— Next button —>
<fa-modifier
fa-origin =»origin.center»
fa-align =»align.nextBtn»
fa-size =»size.btn»
fa-scale =»scale.nextBtn.get()»
fa-translate =»trans.topLayer»>
<fa-surface
class =»one-edge-shadow center-align next-btn»
ng-click =»getPokemon(); nextBtnPressAnim(); frontImgAnim()»>
{{nextBtn}}
</fa-surface>
</fa-modifier>
|
Эта кнопка появляется на первом экране и просто вытаскивает другого покемона из базы данных. Все знакомые вам директивы ng (Angular), такие как ng-click . У меня есть несколько функций здесь. Обратите внимание, что они не разделены запятыми.
Я также связываю значение $scope.nextBtn с {{nextBTn}} в HTML.
Чтобы позволить Famo.us и Angular работать вместе, нам нужно включить $Famo.us в начало нашего файла JavaScript. Вот как вы это делаете:
|
01
02
03
04
05
06
07
08
09
10
|
angular.module(‘famousAngularStarter’)
.controller(‘PokemonCtrl’, [‘$scope’, ‘$http’, ‘$famous’, function ($scope, $http, $famous) {
/* Inject famo.us to DOM */
var View = $famous[‘famous/core/View’ ];
var Modifier = $famous[‘famous/core/Modifier’ ];
var Surface = $famous[‘famous/core/Surface’ ];
var Transform = $famous[‘famous/core/Transform’ ];
var Transitionable = $famous[‘famous/transitions/Transitionable’];
var Timer = $famous[‘famous/utilities/Timer’ ];
|
Анимации
Каким было бы высокопроизводительное приложение без анимации? Famo.us упакован с ними, что позволяет легко начать работу. Вот один для анимации изображения на передней панели.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
/*
* @OnClick: Sets the opacity and scale for the front image when user clicks «Next» btn
* 1) Turns opacity invisible quickly before returning to original opacity, revealing new Pokemon
* 2) Turns scale down before quickly turning it back up to original size
*/
$scope.frontImgAnim = function() {
var hideDuration = 200;
var returnDuration = 1300;
$scope.opac.imgFront.
function returnToOrigOpacity() {
$scope.opac.imgFront.set(1, {duration: returnDuration, curve: «easeIn»})
}
);
$scope.scale.imgFront .set([0.5, 0.5], {duration: hideDuration, curve: «easeIn»},
function returnToOrigSize() {
$scope.scale.imgFront.set([0.8, 0.8], {duration: returnDuration, curve: «easeIn»})
}
)
};
|
Есть несколько типов кривых, которые вы можете использовать здесь. Проверьте документы для получения дополнительной информации. Я также использую функцию обратного вызова returnToOrigSize , чтобы изображение росло, а затем уменьшалось до исходного размера.
Очки разочарования
Я столкнулся с несколькими проблемами по пути.
Директивы FA имеют свои свойства в виде строк
|
1
|
fa-origin =»origin.center»
|
Если у вас есть орфографическая ошибка, приложение будет просто использовать значения по умолчанию для этого свойства. Это меня зацепило несколько раз, поэтому вы видите, что я установил все свои свойства как объект, такой как align.frontName , чтобы его было легче читать.
Добавление классов
В директивах FA вы добавляете несколько классов в виде строк, и они не разделяются запятыми.
|
1
2
3
4
5
|
<fa-surface
class =»one-edge-shadow center-align next-btn»
ng-click =»infoBtnPressAnim(); flip()»>
{{infoBtnText}}
</fa-surface>
|
Если вы пытаетесь добавить классы, создавая поверхности в JavaScript, вы передаете массив строк.
|
1
2
3
4
5
6
|
var logo = new Surface({
properties: {
…
},
classes: [‘backfaceVisibility, class-two’]
});
|
Мне потребовалось некоторое время, чтобы понять это, поскольку я нашел решение только в этом .
Famo.us + Angular кажется устаревшим (на данный момент)
В середине этого проекта я увидел, что Famo.us работает над улучшенной версией фреймворка, который включает в себя смешанный режим. Famo.us + Angular по крайней мере не использует эти дополнения (пока). Это не значит, что FA никуда не денется, так как работает отлично, просто вы не получите новейшие функции.
Ресурсы
- Famo.us Slackchat
- BizSpark, бесплатные лицензии MSFT для разработчиков и веб-хостинг
- Напишите мне с вопросами
- Узнайте, как превратить это в приложение Cordova для мобильных платформ
Больше практического опыта с JavaScript
Эта статья является частью серии веб-разработок от технических евангелистов Microsoft, посвященной практическому изучению JavaScript, проектам с открытым исходным кодом и рекомендациям по взаимодействию, включая браузер Microsoft Edge и новый механизм рендеринга EdgeHTML .
Мы рекомендуем вам протестировать браузеры и устройства, включая Microsoft Edge — браузер по умолчанию для Windows 10 — с бесплатными инструментами на dev.modern.IE :
- Сканирование вашего сайта на наличие устаревших библиотек, проблем с макетом и доступности
- Используйте виртуальные машины для Mac, Linux и Windows
- Удаленно протестируйте Microsoft Edge на своем устройстве
- Coding Lab на GitHub: кросс-браузерное тестирование и лучшие практики
Глубокие технические знания по Microsoft Edge и веб-платформе от наших инженеров и евангелистов:
- Microsoft Edge Web Summit 2015 (что ожидать от нового браузера, новых поддерживаемых стандартов веб-платформ и приглашенных докладчиков из сообщества JavaScript)
- Вау, я могу протестировать Edge & IE на Mac и Linux! (от Рей Банго)
- Продвижение JavaScript без взлома Интернета (от Кристиана Хайльмана)
- Механизм рендеринга краев, который заставляет веб работать просто (от Джейкоба Росси)
- Откройте 3D-рендеринг с помощью WebGL (от Дэвида Катухе, включая проекты Vorlon.js и Babylon.js )
- Размещенные веб-приложения и инновации веб-платформы (от Кевина Хилла и Кирилла Сексенова, в том числе проект manifoldJS )
Больше бесплатных кроссплатформенных инструментов и ресурсов для веб-платформы: