Топ 10 JavaScript и CSS библиотек октября 2018 года

Наша миссия в Техноджеме — держать вас в курсе последних и самых крутых тенденций в мире веб-разработки. Вот почему мы решили каждый месяц выпускать подборку лучших, по нашему мнению, ресурсов на которые мы обратили внимание и считаем своим долгом познакомить с ними вас.

1. Direction Reveal

Этот плагин определяет направление, из которого курсор заходит на блок или покидает его, позволяя применять все виды красивых эффектов и переходов. Он предлагает несколько анимаций CSS из коробки, и вы с помощью этой библиотеки ничто не мешает вам создавать создавать свои собственные эффекты.

Топ 10 JavaScript и CSS библиотек октября 2018 года

2. Toast UI Editor

Это markdown и WYSIWYG редактор , легко переключаемый между режимами markdown и WYSIWYG во время использования. Он предлагает просмотр в реальном времени визуализированного HTML, немедленную проверку синтаксических ошибок и синхронизацию прокрутки между режимами markdown и предварительного просмотра. Поддерживает ряд полезных расширений, таких как color picker, блок диаграмм, блок кода UML и многие другие.

Топ 10 JavaScript и CSS библиотек октября 2018 года

3. Micron.js

Micron — это js библиотека, которая позволяет добавлять различные CSS анимации  в элементы DOM. Интеракции могут управляться HTML атрибутами  или путем привязки методов JavaScript для изменения различных параметров, как то скорость, интенсивность и прочие.

Топ 10 JavaScript и CSS библиотек октября 2018 года

4. BaguetteBox

BaguetteBox — это чистая библиотека JavaScript для создания, так называемых, респонсив лайтбоксов. Он очень легкий, готовый для мобильных устройств, прост в использовании и настройке, а также использует потрясающие CSS3 графические переходы.

Топ 10 JavaScript и CSS библиотек октября 2018 года

Рекомендую к прочтению мою статью Топ 10 JavaScript и CSS библиотек ноября 2018 года в которой мы продолжим знакомство с новыми, интересными, на наш взгляд, библиотеками, представляю вашему вниманию новую подборку ноября 2018.

5. Sticky-Kit

Sticky-kit — это плагин jQuery, который позволяет прикреплять элементы к определенной области на странице, заставляя их придерживаться своих границ. Используя его , вы можете закрепить сайдбар, чтобы он оставался всегда на виду при скролинге.

Топ 10 JavaScript и CSS библиотек октября 2018 года

6. Pretty Checkbox

Это чистая библиотека CSS для создания красивых чекбоксов и переключателей. Поддерживает различные формы, цвета и анимации. Может использовать пользовательские значки шрифтов, значки SVG и умеет в SCSS кастомизацию.

Топ 10 JavaScript и CSS библиотек октября 2018 года

7. Bulma

Это бесплатный CSS фреймворк с открытым исходным кодом базирующийся на Flexbox. У Bulma есть 39 файлов .sass, которые можно импортировать отдельно. Вы можете легко его настроить  и создать свои собственные темы. Каждый элемент в Bulma является мобильно-ориентированным и оптимизирован для небольших экранов.

8. T-scroll

Мощная и простая в использовании библиотека прокрутки с полезными опциями и анимациями. Он поставляется с ванильным Sass и включает в себя большое количество CSS3 анимаций , таких как bounceIn, fadeIn, flip, rotate, zoom и многое другое. T-scroll совместим с большинством современных браузеров, включая IE 10+, Firefox, Chrome и Safari.

Топ 10 JavaScript и CSS библиотек октября 2018 года

9. Iconate

JavaScript библиотека , которая позволяет вам кликом мыши трансформировать одну иконку в другую с помощью множества плавных анимаций. Iconate работает со всеми шрифтами значков CSS — просто добавьте значок в свой HTML и используйте простой JavaScript API, чтобы выбрать, во что его преобразовать, и какую из 15 анимаций использовать.

Топ 10 JavaScript и CSS библиотек октября 2018 года

10. Simple Icons

Огромная коллекция бесплатных значков для популярных социальных сетей, приложений, сервисов и прочиих брендов. Поскольку все значки сделаны в SVG, их можно масштабировать до любого размера, не опасаясь пикселизации или пятен. Благодаря SVG они очень легковесные — большинство из них занимает менее 500 байт, более детализированные — 1-2 КБ.

Топ 10 JavaScript и CSS библиотек октября 2018 года

А чем пользуетесь Вы? Если у вас есть на примете какие-то интересные Javascript и CSS библиотеки, просьба поделиться в комментариях.

Создание мобильных приложений с Cordova и Vue.js

Cordova это фреймворк, с которым вы можете создавать мобильные приложения с использование веб-технологий, таких как HTML, Javascript и CSS. Это позволяет создавать приложения сразу для нескольких платформ (к примеру, на Android и iOS) с общей кодовой базой. Несмотря на то, что вам всё ещё нужны платформо-зависимые технологии, типа Android SDK и XCode для сборки, вы можете создавать приложения без использования нативного Android- или iOS-кода.

А так как наш код это HTML и Javascript, мы легко можем использовать любимые Javascript библиотеки вроде Vue.js с Cordova.

И сегодня мы рассмотрим пример создания мобильного приложения с Cordova и Vue.js.

Исходный код проекта можно взять здесь.

Подготовка

Перед тем, как мы приступим к нашей задаче, проверьте, установлены ли у вас необходимые библиотеки:

  • Скачайте Node.js
  • Установите Cordova: npm install -g cordova
  • Ознакомьтесь с основами Vue.js
Создание проекта Cordova

Создадим проект и назовём его RandomWord:


cordova create RandomWord
cd RandomWord

Это создаст иерархию директорий:

Создание мобильных приложений с Cordova и Vue.js


  • config.xml — содержит информацию о приложении, используемых плагинах и платформах
  • platforms — содержит библиотеки Cordova для целевых платформ, на которых приложение будет запущено
  • plugins — содержит библиотеки плагинов Cordova, используемые в приложении. Они предоставляют приложению доступ к устройству: к камере, состоянию батареи и т.п.
  • www — содержит исходный код приложения на HTML, Javascript и CSS
  • hooks — содержит скрипты для настройки системы сборки приложения

Добавим платформу Android:

cordova platform add android --save

Эта команда добавит библиотеку платформы Android в папку platforms (platforms/android).


...
    <engine name="android" spec="~5.2.1" />
</widget>

Проверим установленные зависимости для сборки/запуска приложений Android с Cordova:

cordova requirements

Собираем наше приложение под Android:

cordova build android

Подключите ваш телефон к компьютеру и запустите приложение:

cordova run android

Если не подключать устройство, Cordova запустит приложение в эмуляторе. Наше приложение пока лишь показывает картинку и надпись:

Создание мобильных приложений с Cordova и Vue.js

Для построения приложения под iOS нужно выполнить те же шаги, заменив в командах android на ios. Также есть вариант использовать ваш браузер вместо мобильного устройства, установив платформу browser.

Изменим немного файл config.xml:


<?xml version='1.0' encoding='utf-8'?>
<widget id="io.coligo.randomword" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>RandomWord</name>
    <description>
        A mobile app for generating a random word.
    </description>
    <author email="michaelviveros@gmail.com" href="http://www.michaelviveros.com/">
        Michael Viveros
    </author>
    ...
Добавляем Vue.js

Добавим Vue.js CDN в конец файла www/index.html:


...
        <script type="text/javascript" src="cordova.js"></script>
        <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Для того, чтобы приложение могло вызывать библиотеку Vue.js, добавим строчку в конец мета-тега Content Security Policy (CSP) в www/index.html:

; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js 'unsafe-eval'

CSP позволяет создать список разрешённых источников и разрешает браузеру обрабатывать контент только из этих источников.

Часть мета-тега CSP script-src отвечает за то, откуда будут браться скрипты, исполняемые нашим приложением.

  • ’self’ — разрешены скрипты только из этого же источника, например, www/js/index.js
  • http://cdn.jsdelivr.net/vue/1.0.16/vue.js — разрешена библиотека Vue.js
  • ’unsafe-eval’ — разрешено выполнение небезопасного кода, так как некоторый код из Vue.js использует строки для генерации функций

Мета-тег CSP должен выглядеть так:

После замены кода в теле www/index.html некоторым кодом Vue.js, этот файл должен стать таким:


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js 'unsafe-eval'">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Random Word</title>
    </head>
    <body>
        <div id="vue-instance" class="app">
            <h1>Random Word</h1>
            <button id="btn-get-random-word" @click="getRandomWord">Get Random Word</button>
            <p>{{ randomWord }}</p>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Теперь добавим немного Javascript для генерации и вывода случайного слова.

В www/js/index.js уже есть код, он может сменить цвет фона или заголовок, при получении приложением события deviceready. И нам не нужно пока лезть в эти методы. Однако, попробуйте сами разобраться с методом bindEvents для выполнения различных действий на различных этапах жизненного цикла приложения.

Мы добавим новый метод в файл www/js/index.js, назовём его setupVue, он будет создавать новый объект Vue и привязывать его к блоку random word. Новый объект Vue будет содержать метод getRandomWord, извлекающий случайное слово из списка слов при нажатии кнопки Get Random Word.


var app = {
    initialize: function() {
        this.bindEvents();
        this.setupVue();
    },
    ...
    setupVue: function() {
        var vm = new Vue({
            el: "#vue-instance",
            data: {
                randomWord: '',
                words: [
                    'formidable',
                    'gracious',
                    'daft',
                    'mundane',
                    'onomatopoeia'
                ]
            },
            methods: {
                getRandomWord: function() {
                    var randomIndex = Math.floor(Math.random() * this.words.length);
                    this.randomWord = this.words[randomIndex];
                }
            }
        });
    }
};

app.initialize();

После удаления ненужного кода, файл www/js/index.js будет таким:


var app = {
    initialize: function() {
        this.bindEvents();
        this.setupVue();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    },
    setupVue: function() {
        var vm = new Vue({
            el: "#vue-instance",
            data: {
                randomWord: '',
                words: [
                    'formidable',
                    'gracious',
                    'daft',
                    'mundane',
                    'onomatopoeia'
                ]
            },
            methods: {
                getRandomWord: function() {
                    var randomIndex = Math.floor(Math.random() * this.words.length);
                    this.randomWord = this.words[randomIndex];
                }
            }
        });
    }
};

app.initialize();

Соберём приложение, подключим телефон и запустим:

cordova build android
cordova run android

Приложение теперь выглядит примерно так:

Создание мобильных приложений с Cordova и Vue.js
HTTP запросы с vue-resource

Вместо того, чтобы использовать заданный список слов в нашем приложении, используем для этого специальный веб-сервис, например, этот: Wordnik Random Word API

В конец мета-тега CSP добавьте следующий код для разрешения работать с этим ресурсом:

; connect-src http://api.wordnik.com:80/v4/words.json/randomWord

В connect-src мы указали приложению, куда разрешено делать http-запросы.

Добавим библиотеку vue-resource для создание таких запросов.

index.html немного изменится:


<!DOCTYPE html>
...
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; script-src 'self' http://cdn.jsdelivr.net/vue/1.0.16/vue.js https://cdn.jsdelivr.net/vue.resource/0.7.0/vue-resource.min.js 'unsafe-eval'; connect-src http://api.wordnik.com:80/v4/words.json/randomWord">
...
        <script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
        <script src="https://cdn.jsdelivr.net/vue.resource/0.7.0/vue-resource.min.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Отредактируем файл www/js/index.js для использования веб-сервиса:


...
    setupVue: function() {
        var vm = new Vue({
            el: "#vue-instance",
            data: {
                randomWord: ''
            },
            methods: {
                getRandomWord: function() {
                    this.randomWord = '...';
                    this.$http.get(
                        'http://api.wordnik.com:80/v4/words.json/randomWord?api_key=a2a73e7b926c924fad7001ca3111acd55af2ffabf50eb4ae5'
                    ).then(function (response) {
                        this.randomWord = response.data.word;
                    }, function (error) {
                        alert(error.data);
                    });
                }
            }
        });
    }
};

app.initialize();

Соберём и запустим приложение:

cordova build android
cordova run android

Приложение выглядит как раньше, однако слова берутся уже с помощью Random word API.

Компоненты Vue

Vueify это библиотека для Vue.js, помогающая разделить интерфейс на небольшие компоненты, каждый со своим HTML, JavaScript и CSS. Приложение становится более модульным и вы можете вызывать отдельные его компоненты в иерархическом порядке.

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

Так должна выглядеть структура папок после добавления Vue Component:

Создание мобильных приложений с Cordova и Vue.js



Создадим компонент, вызывающий наш метод получения слова в www/js/random-word.vue:


<template>
  <div class="app">      
    <h1>Random Word</h1>
    <button id="btn-get-random-word" @click="getRandomWord">Get Random Word</button>
    <p>{{randomWord}}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      randomWord: ''
    }
  },
  methods: {
    getRandomWord: function() {
        this.randomWord = '...';
        this.$http.get(
            'http://api.wordnik.com:80/v4/words.json/randomWord?api_key=a2a73e7b926c924fad7001ca3111acd55af2ffabf50eb4ae5'
        ).then(function (response) {
            this.randomWord = response.data.word;
        }, function (error) {
            alert(error.data);
        });
    }
  }
}
</script>


Разметка HTML из файла www/index.html теперь находится в теге template, а Javascript код из www/js/index.js находится в теге script файла random-word.vue.

Создадим новый объект Vue, содержащий этот компонент в новом файле www/js/main.js:


var Vue = require('vue');
var VueResource = require('vue-resource');
var RandomWord = require('./random-word.vue');

Vue.use(VueResource);

var vm = new Vue({
  el: 'body',
  components: {
    'random-word': RandomWord
  }
});

Для склеивания компонентов мы используем browserify и vueify для создания файла bundle.js. Создадим новую папку scripts и в ней файл vueify-build.js.

scripts/vueify-build.js будет таким:


var fs = require('fs');
var browserify = require('browserify');
var vueify = require('vueify');

browserify('www/js/main.js')
  .transform(vueify)
  .bundle()
  .pipe(fs.createWriteStream('www/js/bundle.js'))

Раньше мы вызывали библиотеки Vue.js с CDN в www/index.html, но сейчас www/js/main.js использует javascript для этого. Создадим файл package.json для синхронизации всех зависимостей:


{
  "name": "random-word",
  "version": "1.0.0",
  "description": "A mobile app for generating a random word",
  "main": "index.js",
  "dependencies": {
    "browserify": "~13.0.1",
    "vue": "~1.0.24",
    "vue-resource": "~0.7.4",
    "vueify": "~8.5.4",
    "babel-core": "6.9.1",
    "babel-preset-es2015": "6.9.0",
    "babel-runtime": "6.9.2",
    "babel-plugin-transform-runtime": "6.9.0",
    "vue-hot-reload-api": "2.0.1"
  },
  "author": "Michael Viveros",
  "license": "Apache version 2.0"
}

Установить все зависимости проекта теперь можно одной командой:

npm install
Добавим хук в конец файла config.xml, чтобы Cordova знала о необходимости склеивания компонента перед сборкой приложения:


...
    <hook type="before_compile" src="scripts/vueify-build.js" />
</widget>


Мы помним, что scripts/vueify-build.js создаст собранный компонент и положит его в www/js/bundle.js

Добавим вызов компонента в тело www/index.html, создав тег random-word и тег script, вызывающий наш склеенный ранее компонент.


...
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Random Word</title>
    </head>
    <body>
        <random-word></random-word>
        <script src="js/bundle.js"></script>

        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript" src="cordova.js"></script>
    </body>
</html>

Помните, что тег link в www/index.html задаёт CSS приложения, а тег div в www/js/random-word.vue использует класс «app» из CSS.

Поскольку мы перенесли логику в другое место, теперь мы можем удалить метод setupVue из www/js/index.js:


var app = {
    initialize: function() {
        this.bindEvents();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    }
};

app.initialize();

Соберём и запустим приложение:

cordova build android
cordova run android
Заключение

Разрабатывать мобильные приложения с Cordova очень просто. А с Vue.js вы можете использовать огромное количество её функций в мобильных приложениях.

Написано по материалам Building a Mobile App with Cordova and Vue.js by Michael Viveros

Создание кроссплатформенного плеера для SoundCloud® с Fuse

Создание кроссплатформенного плеера для SoundCloud® с Fuse

Мы постоянно получаем запросы от наших пользователей, которые хотят увидеть, как выглядят “реальные программы”, сделанные с Fuse. Наш учебник специально предназначен для быстрого начала работы с Fuse, но при этом он пока не содержит описаний сложных задач.

Поэтому я решил сделать полную программу, с публикацией в магазины приложений. Она будет служить примером по-настоящему сложных задач и будет великолепным мастер-классом.

Приложение будет работать с реальным бекендом, оно будет кроссплатформенным (работать в Android и iOS) и будет использовать несколько интересных нативных интеграций на обеих платформах.

Как мы видим, SoundCloud® имеет всё необходимое:

  • Они предоставляют REST API (и он бесплатен)
  • Есть много контента для работы (картинки и музыка)
  • Нашему приложению понадобятся нативные компоненты (контролы для управления музыкой и т.п.)

Перед тем, как начать…

Вы можете не устанавливать Fuse и не читать код на Github, чтобы увидеть готовый результат.

Внимание: приложение FuseCloud это неофициальный плеер для SoundCloud, и никаким образом не связано с SoundCloud. Оно просто использует SoundCloud API.

Реализация

Есть три главных подзадачи: пользовательский интерфейс, написанный на UX и JavaScript; обёртка вокруг SoundCloud REST API; нативный музыкальный плеер.

Навигация

Я использовал компоненты Router и Navigator для построения большей части навигации, с единственным исключением для PageControl в главном представлении, в котором вы можете переключаться между тремя табами (лента новостей, поиск, избранное). После создания каждой страницы приложения отдельным компонентом, навигация будет примерно такой:

// fusecloudnavigationstructure.ux
<Navigator DefaultTemplate="main">
    
    <FuseCloud.MainPage ux:Name="main">
        <PageControl ux:Name="pageControl" Active="searchPage">
            <Page ux:Name="newsFeedPage" />
            <Page ux:Name="searchPage" />
            <Page ux:Name="favoritesPage" />
        </PageControl>
    </FuseCloud.MainPage>
    
    <FuseCloud.CommentsPage ux:Template="comments" router="router" />
    
    <FuseCloud.TrackDetailsPage ux:Name="track" router="router"/>
    
</Navigator>
Бесконечная прокрутка

Благодаря новым возможностям Fuse, я легко создал плавную бесконечную прокрутку для отображения всех комментариев к каждой композиции. Вставляя отдельные комментарии в блок Deferred, я защищён от глюков при автоматической подгрузке новых элементов. Ниже вы можете увидеть пример UX-кода для создания такой прокрутки:

// fusecloudendlessscroller.ux
<ScrollView ClipToBounds="False">
    <StackPanel>
        <Each Items="{comments}">
            <Deferred>
                <FuseCloud.DividerLine Alignment="Top"/>
                <FuseCloud.Comment ux:Name="comment" ThumbnailUrl="{avatar_url}" Username="{username}" Body="{body}" />
            </Deferred>
        </Each>
    </StackPanel>
    <Scrolled To="End" Within="100">
        <Callback Handler="{showMoreComments}" />
    </Scrolled>
</ScrollView>

Прокрутка на 100 точек от нижнего края приложения вызывает JavaScript-функцию, которая подгружает следующие комментарии:

// fusecloudendlessscroller.js
function showMoreComments() {
    if (nCommentsShowing < allComments.length) {
        nCommentsShowing += nCommentsPerPage;
        while (comments.length < nCommentsShowing && comments.length < allComments.length - 1) {
            comments.add(allComments.getAt(comments.length));
        }
    }
}

Замутнение фона

Экран проигрывателя показывает изображение альбома текущей дорожки посередине страницы, при этом заполняя весь фон затемнённой копией этого же изображения. В Fuse такое делается одной строчкой кода: , но замутнение больших элементов может плохо отразиться на производительности. Поэтому я использую классический трюк с программной GPU-обработкой для улучшения скорости:

// fusecloudscaledblur.ux
<FuseCloud.AlbumArt Width="20%" Height="20%">
    <Blur Radius="2"/>
    <Scaling Factor="5" />
</FuseCloud.AlbumArt>

 

Здесь я уменьшаю размер изображения до 20% от оригинального и замутняю уменьшенное изображение, затем увеличиваю получившееся изображение до нормального размера.

Создание кроссплатформенного плеера для SoundCloud® с Fuse

Работаем с SoundCloud API

Вообще это несложная задача и в ней нет никаких специфичных для Fuse техник. Я структурировал обёртку, поэтому каждый запрос возвращает promise. Модель приложения была использована как интерфейс к API через набор функций-геттеров, возвращавших promise-ы в Observable. Код ниже наглядно иллюстрирует этот подход:

Функция, используемая для получения статуса лайка для трека, возвращает promise:

// fusecloudislikingtrackfetch.js
function isLikingTrack(trackId) {
    return Auth.getAccessToken()
        .then(function(token) {
            return FuseCloudGet("me/favorites/" + trackId, {}, token);
        });
}

 

Модель превращает этот promise в observable, используя удобную функцию (DelayedObservable):

// fusecloudislikingtrackobservable.js
function GetIsLikingTrack(trackId) {
    return DelayedObservable(function(obs) {
        FuseCloud.isLikingTrack(trackId)
            .then(function(result) {
                obs.add(result);
            });
    });
}

 

Это реально удобно, учитывая что возвращённый observable будет заполнен сразу при получении данных. Затем мы можем сделать привязку к нему и не беспокоиться об обратных вызовах или обновлениях интерфейса приложения.

Функция DelayedObservable работает как мост между API, основанной на promise-ах, и API, основанной на Observable:

// fuseclouddelayedobservable.js
function DelayedObservable(getter) {
    var ret = Observable();
    getter(ret);
    return ret;
}

 

Эта функция отвечает за обновление Observable при загрузке данных.

OAuth 2.0

SoundCloud API позволяет авторизоваться с помощью протокола OAuth 2.0. Используя модуль InterApp, я легко перекидываю пользователя на авторизацию с помощью нативного браузера:

// fusecloudlaunchuri.js
var uri = "https://soundcloud.com/connect?client_id=" + clientId
        + "&display=popup"
        + "&response_type=code"
        + "&redirect_uri=fuse-soundcloud://fuse";
InterApp.launchUri(uri);

 

В URL выше передаётся URI обратного вызова, который SoundCloud использует для возврата токена. Fuse позволяет зарегистрировать свою URI-схему в файле проекта:

// fusecloudcustomurischeme.json
"Mobile":{
    "UriScheme": "fuse-soundcloud"
}

 

Таким образом, SoundCloud API автоматически вернётся в нашу программу, как только токен доступа будет готов.

Создание кроссплатформенного аудиоплеера

Реализация обёртки для нативных плееров была наиболее интересной частью процесса. Частично из-за того, что API для этого различны у Android и iOS, но также по причине монолитной природы медиа-плееров. Я начал с минимального набора требований.

Наш StreamingPlayer должен:

  • Транслировать аудио по URL
  • Продолжать играть, когда приложение уходит в фон
  • Позволять переключаться между треками, пока приложение находится в фоне (используя нативные контролы на экране блокировки)
  • Отображать обложку альбома на экране блокировки

Создание кроссплатформенного плеера для SoundCloud® с Fuse

На бумаге это не кажется слишком сложной задачей, но на деле она оказалась настоящим вызовом.

Прежде всего, подключение к нативному аудиоплееру для проигрывания URL было суперпростым. API у Android MediaPlayer-а и AVPlayer у iOS предлагают это прямо из коробки. Моей начальной задумкой было использовать минимальную обёртку вокруг обоих этих API и просто делать остальную работу (типа управления плейлистами и состоянием) в JavaScript. Но ограничение на фоновое выполнение JS на этих платформах поставило крест на этом (одно из наших требований — возможность использовать контролы на экране блокировки).

Это означало, что я должен реализовать работу с плейлистами в нативном коде, при этом учитывая особенности Android и iOS. К счастью, всё оказалось гораздо проще, так как возможности внешнего кода Fuse позволяют вам легко интегрировать код на Java и Objective-C в проекты Fuse. Это очень удобно!

Другой интересной задачей было получение текущего состояния плеера для обоих компонентов, MediaPlayer и AVPlayer. Оба этих API имеют разные модели состояния и разные пути управления ими, но я нашёл универсальный способ.

И, наконец, работа с экраном блокировки. В iOS это крайне просто; достаточно зарегистрировать несколько системных вызовов. В Android же это не такая простая задача. В API, начиная с уровня 21, Android может получать медиа-нотификации, которые замещают обычные контролы на экране блокировки. Но нужно копать в сторону системы intent-ов для настройки коммуникации между нотификациями и фоновой службой.

Возможности

В приложение FuseCloud встроены очень большие возможности и механизмы, и так как я люблю перечисления, вот небольшой список фич, заложенных в этой программе (и исходном коде):

  • Аутентификация в SoundCloud® по протоколу OAuth 2.0
  • Использование пакета InterApp для запуска url во внешнем браузере и передача отклика по URI
  • Автоматическое обновление некорректных токенов
  • Получение данных по REST API
  • Лента новостей, поиск треков, избранное
  • Возможность поставить лайк и дизлайк треку
  • Обложки треков
  • Отображение комментариев к треку
  • Размещение комментариев
  • Статистика пользователя
  • Смахивание влево/вправо для переключения дорожки
  • Потягивание экрана для обновления
  • Бесконечный список прокрутки
  • Смахивание для показа действий с элементом (дизлайк в избранном)
  • Сохранение состояния UI с использованием Storage API (приветственная информация показывается только один раз при начале работы с программой)®
  • HTTP Audio StreamingPlayer для iOS и Android
  • Трансляция музыки из SoundCloud®
  • Настраиваемая панель перемотки
  • Фоновое проигрывание
  • Контролы на экране блокировки в iOS и Android
  • iOS: следующий, предыдущий, играть/пауза, перемотка на экране блокировки
  • Обложка альбома на экране блокировки
  • Нотификации в Android: следующий, предыдущий, играть/пауза
  • Показ обложки альбома в нотификации и в фоне
  • Плейлисты
  • Автопроигрывание следующего при окончании трека

Выводы и загрузки

Было реально классно работать над этим проектом. Я необъективен, но Fuse реально впечатлила меня  — в который раз.

И механизмы внешнего кода Fuse оказались действительно хорошим способом создания нативных компонентов. Они позволяют использовать документацию к API каждой платформы на своём языке, где это возможно, и без обёрток на JavaScript.

Вы можете скачать приложение FuseCloud для Android и iOS в Apple App Store, в Google Play, и исходный код на Github.

Внимание: ещё раз о создании “реальной” программы (с нативными компонентами и интеграциями с бекендом) — вы почти наверняка столкнетесь с некоторыми трудностями. Мы постоянно улучшаем нашу документацию, но если всё-таки встретите такой случай, дайте знать об этом нам и сообществу, и мы с радостью вам поможем 🙂

Узнать больше о Fuse можно посмотрев постоянно растущий список примеров (с исходным кодом, конечно), вступайте в наше сообщество (у нас есть классный форум и группа в Slack) или подписывайтесь на нас в Twitter или Facebook.

Автор оригинала Kristian Hasselknippe, Software Engineer at Fuse

Adblock
detector