Логотип Electron
Логотип Electron
Фреймворк Electron разработан в GitHub и носил раньше название Atom shell. Пожалуй, самое известное приложение, написанное с его помощью, — текстовый редактор Atom, а еще — клиент Slack для настольных компьютеров, которым очень активно пользуются в нашей редакции. Из других интересных проектов — мультипротокольный клиент мгновенных сообщений Franz, Git-клиент GitKraken, GUI-клиент к хорошо известной Node.js-разработчикам утилите Yeoman yeoman-app и даже Microsoft Visual Studio Code.

Electron позволяет создавать кросс-платформенные приложения для настольных компьютеров с использованием чистого JavaScript. Поддерживаются основные операционные системы: macOS, Linux, Windows. Он сочетает в себе лучшие стороны Node.js и Chromium, но при этом ориентирован на разработку десктопных приложений.

Само собой напрашивается сравнение Electron с проектом Cordova, который аналогичным образом позволяет превратить веб-приложение в мобильное приложение для основных мобильных платформ. Так когда же нам может пригодиться именно Electron? Варианты следующие:

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

WWW


Читаем доки здесь. Перевод на русский язык здесь.
 

Что будем делать

Мы возьмем готовый виджет, «обернем» его в приложение Electron и добавим стандартные элементы интерфейса операционной системы, такие как иконка в области уведомлений, стандартные системные диалоги, вызов внешнего приложения, главное меню, горячие клавиши.

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

 

Подготовка

 

Иконки

Для приложения нам понадобится несколько иконок. Я брал их из набора ie_Bright с сайта iconfinder.com; можно взять другие на свой вкус. Для изображений, используемых для иконки в области уведомлений под Windows, рекомендуются файлы .ico, но мы для простоты возьмем только PNG-файлы.

Имя файла Назначение Изображение
player.png Иконка приложения
player.png#26759185
player.png
play.png Начать проигрывание
play.png#26759185
play.png
pause.png Приостановить
pause.png#26759185
pause.png
prev.png Предыдущая композиция
prev.png#26759185
prev.png
next.png Следующая композиция
next.png#26759185
next.png

Поместим иконки в подкаталог assets/img/ проекта.

 

Node.js

Предполагается, что на компьютере установлен Node.js версии не ниже 6.6; загрузить ее можно здесь.

$ node -v
v6.6.0
 

Операционная система

Примеры подготовлены для выполнения на компьютере, работающем под управлением ОС Linux и macOS.

 

Минимальное приложение Electron

Начнем с создания минимального приложения Electron. Для этого создадим каталог проекта, например electron-demo, и перейдем в него:

$ mkdir electron-demo
$ cd electron-demo

Добавим в наш проект два файла — минимальный index.html, который будет основным интерфейсом нашего приложения:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    Welcome to Electron!
</body>
</html>

и index.js со следующим содержимым:

const path = require('path')
const electron = require('electron')
const {app, BrowserWindow} = electron

// Ссылка на объект окна; если ее не будет, окно закроется автоматически, когда сборщик мусора высвободит память из-под объекта JavaScript
let win = null

// Путь к иконкам приложения
const iconBasePath = path.join(__dirname, 'assets', 'img')


// Создание окна браузера и обработка его событий
function createWindow () {
    const APP_ICON_NAME = 'player.png'
    const iconPath = path.join(iconBasePath, APP_ICON_NAME)

    // Задаем параметры для создания окна браузера
    let options = {
        width: 800, height: 550,
        title: 'Electron SoundCloud Player', // Не будет работать, если в `.html` есть тег `title`
        icon: iconPath,
        webPreferences: {
            devTools: true, // По умолчанию — `true` для показа DevTools
        }
    }
    // Создаем окно браузера
    win = new BrowserWindow(options)

    // и загружаем index.html приложения
    win.loadURL(`file://${__dirname}/index.html`)

    // Событие во время закрытия окна
    win.on('closed', (e) => {
        // Это то время, когда нужно удалить соответствующий объект
        // Убираем ссылку на объект окна. В многооконных приложениях окна обычно будут храниться в массиве
        win = null
    })

    let webContents = win.webContents

    // Открываем DevTools
    webContents.openDevTools()
}

// Этот событие произойдет, когда Electron завершит
// инициализацию и будет готов к созданию окон браузера
// Многие методы API могут использоваться только после этого события
app.on('ready', createWindow);

// Выйти из приложения, когда все окна закрыты
app.on('window-all-closed', () => {
    // На macOS приложения и их меню остаются активными до тех пор, пока
    // пользователь не выйдет из них явно с помощью Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

app.on('activate', () => {
    // На macOS, как правило, при клике на иконке в доке (и если нет других
    // открытых окон), окно в приложении пересоздается
    if (win === null) {
        createWindow()
    }
})

Инициализируем файл package.json проекта менеджера пакетов npm, ответив на необходимые вопросы.

$ npm init

Нужно проверить, что в package.json, получившемся в результате, значение свойства main равно main.js (соответствует значению, введенному при запросе entry point во время выполнения команды npm init), в противном случае его необходимо скорректировать вручную, чтобы оно соответствовало имени главного .js-файла проекта.

Electron можно установить только для нашего проекта:

$ npm install --save electron

или глобально:

$ npm install -g electron

Пора запускать! Если Electron был установлен локально, это делается следующей строкой (если он был установлен глобально, путь указывать необязательно):

$ ./node_modules/.bin/electron .

Через несколько мгновений откроется окно нашего первого приложения.

Первое приложение
Первое приложение

Обрати внимание, что сразу же открыто привычное окно DevTools. Заголовок и текст окна соответствуют заданным; кроме того, у приложения есть типовое главное меню.

 

Виджет SoundCloud

Виджет SoundCloud встраивается в веб-страницу как IFrame и позволяет проигрывать отдельные композиции с сайта SoundCloud или их списки. Он предоставляет базовый интерфейс для управления проигрыванием и разнообразную информацию о композиции.

 

API виджета

Методы виджета

Из методов API виджета для управления проигрыванием мы будем использовать следующие:

  • play — начать проигрывание композиции;
  • pause — приостановить проигрывание композиции (пауза);
  • toggle — переключить проигрывание / приостановка;
  • prev — перейти к предыдущей композиции (для списка);
  • next — перейти к следующей композиции (для списка);
  • bind — добавить обработчик события виджета.

В числе прочих методов: skip, load, seekTo, setVolume, unbind.

События виджета

События виджета делятся на две группы: аудиособытия и события пользовательского интерфейса.

Аудиособытия связаны с проигрываемой композицией и уведомляют об изменениях ее состояния в проигрывателе, передавая объект с информацией о текущей позиции в проигрываемом файле или прогрессе загрузки (relativePosition, loadProgress, currentPosition).
События пользовательского интерфейса виджета уведомляют о действиях пользователя, не связанных напрямую с проигрыванием композиции.

Мы используем следующие события:

  • READY — виджет загрузил данные и готов принимать внешние вызовы;
  • PLAY — начато проигрывание композиции;
  • PAUSE — проигрывание композиции приостановлено.

Остальные события: LOAD_PROGRESS, PLAY_PROGRESS, FINISH, SEEK, CLICK_DOWNLOAD, OPEN_SHARE_PANEL, ERROR.

Дополнительно можно получить информацию о текущем состоянии виджета с помощью методов getVolume, getDuration, getPosition, getSounds, getCurrentSound, getCurrentSoundIndex, isPaused. Информация возвращается в callback-функции. Из них нам понадобится метод getCurrentSound, возвращающий информацию о текущей композиции.

 

Добавление виджета на страницу

Для того чтобы отобразить на нашей странице виджет SoundCloud, внутри элемента <body> добавим элемент <iframe>, в котором загрузится сам виджет:

<!-- виджет SoundCloud -->
<iframe id="sc-widget" width="100%" height="450" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/playlists/178009618&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;visual=true"></iframe>

Полный список параметров виджета приведен здесь: SoundCloud Player Widget — Customize Parameters (для предыдущей версии, использующей Flash).

Для выбора композиции или их списка и настройки визуального представления виджета можно нажать кнопку Share на понравившемся списке композиций (если выбрана отдельная композиция, то будет невозможно перемещаться к следующей/предыдущей композиции), выбрать закладку Embed и скопировать предлагаемый код; установив галочку More Options, можно настроить несколько дополнительных параметров.

Можем перезапустить приложение, чтобы убедиться, что виджет действительно загрузился внутри нашего приложения.

 

Инициализация API виджета SoundCloud

Для доступа к API виджета необходимо добавить в тег <head> загрузку следующего сценария:

<script src="https://w.soundcloud.com/player/api.js" type="text/javascript"></script>

Туда же добавим загрузку файла, в котором будут размещаться основные функции браузерной части приложения:

<script src="./soundcloud.js" type="text/javascript"></script>

А тег <body> дополним кнопками управления проигрыванием:

<div>
  <button id="action-widget-play">Play</button>
  <button id="action-widget-pause">Pause</button>
  <button id="action-widget-toggle">Toggle</button>
  <button id="action-widget-prev">Prev</button>
  <button id="action-widget-next">Next</button>
</div>

Создадим файл soundcloud.js, добавив в него функцию, которая будет выполняться при загрузке окна браузера:

let initSC = function() {
  const {ipcRenderer} = require('electron')

  let widgetIframe = document.getElementById('sc-widget'), // IFrame виджета
      widget       = SC.Widget(widgetIframe)               // Сам виджет
  console.log('widget:', widget)
}

И собственно вызов этой функции по событию window onload:

// Вызвать основную функцию по событию onload объекта window
window.addEventListener('load', function load(event){
    // Удалить listener, так как он больше не нужен
    window.removeEventListener('load', load, false)
    // Вызов основного метода
    initSC()
}, false)

Теперь при запуске приложения в консоль должен быть выведен объект widget.

 

Методы и события API виджета SoundCloud

Привяжем методы виджета, предназначенные для управления проигрыванием композиции, напрямую к кнопкам управления на странице (в функции initSC):

Продолжение доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все материалы на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи один материал

Заинтересовала информация, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для материалов, опубликованных более двух месяцев назад.


2 комментария

  1. Аватар

    Alchemist

    24.01.2017 at 06:14

    А одним архивом проект можно скачать где нибудь?

  2. Аватар

    Alchemist

    24.01.2017 at 06:27

    И ещё вопрос: вы уверены в строке «Добавим в файл main.js:» ?
    О файле main.js речи не шло до этой строки.

Оставить мнение

Check Also

Хроники битвы при Denuvo. Как «непробиваемая» игровая защита EA Origin оказалась пробиваемой

Защита от пиратства Denuvo пришла на смену SecuROM и связана с одним действующим лицом – Р…