Статьи

Создать многопользовательскую презентацию с Reveal.js

Создание впечатляющей презентации — это искусство. В течение долгого времени PowerPoint фактически оставался единственным инструментом для создания презентаций.

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

Затем появились классные библиотеки презентаций, основанные на HTML5 и CSS3. Reveal.js — очень популярная библиотека для создания потрясающих презентаций.

Websockets — это новый стандарт, определенный как часть спецификации HTML5, который обеспечивает двунаправленную полнодуплексную связь в браузерах. Существует ряд библиотек JavaScript, облегчающих работу с Websockets, из которых Socket.IO является выдающимся.

В этой статье мы обсудим, как создать презентацию Reveal.js, которой могут управлять несколько пользователей. Мы будем использовать Socket.IO для отправки и получения событий смены слайдов в режиме реального времени. Reveal.js уже поставляется с плагином мультиплексора, но его немного сложно настроить, поэтому мы пока проигнорируем это. Давайте сосредоточимся на том, как мы можем написать сервер Socket.IO, который будет соответствовать нашей цели.

Предпосылки

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

  • Node.js
  • йомен
  • хрюкать
  • Беседка

Начальные шаги

Сначала мы настроим сервер express.js. Yeoman упрощает установку и запуск сервера express.js с помощью генераторов. Итак, сначала мы установим экспресс-генератор yeoman, используя npm.

$ npm install –g generator-express 

Это установит экспресс-генератор в глобальном масштабе. Теперь давайте настроим сервер.

 $ yo express 

Это спросит вас, какой тип экспресс он должен установить. Вы можете выбрать Basic или MVC; в нашем случае нам нужна только базовая настройка. Затем он установит несколько модулей npm вместе с файлами bower.json и Gruntfile.js. При наличии только необходимых файлов каталог приложения будет выглядеть примерно так:

Ru── Gruntfile.js
App── app.js
Ower── bower.json
Node── node_modules
Express ├── экспресс
G ├── хрюкать
G ├── grunt-contrib-watch
G ├── хрюкать-развиваться
J ├── нефрит
Request └── запрос
Package── package.json
Public── публично
│ ├── компоненты
│ ├── css
Im ├── img
│ └── js
Views── просмотров

Теперь давайте запустим экспресс-сервер, используя grunt.

 $ grunt Running "develop:server" (develop) task >> started application "app.js". Running "watch" task Express server listening on port 3000 

Yeoman создал для нас файл app.js по умолчанию, который содержит необходимые настройки для запуска сервера. Также обратите внимание, что он поставляется с библиотекой «watch», которая будет отслеживать изменения в коде и автоматически перезагружать сервер, поэтому нам не нужно делать это вручную. Прежде чем мы пойдем дальше, мы установим и настроим библиотеку reve.js, используя bower. Установкаive.js довольно прост и понятен. Просто введите следующую команду в терминале.

 $ bower install reveal.js --save 

При этом будет загружена последняя стабильная версия библиотекикартEW.js из Github, и она будет установлена ​​в каталог public / components. Опция --save автоматически обновляет раздел зависимостей в файле bower.json с помощьюкартирн.js.

Теперь у нас есть все, что нам нужно для создания нашего сервера презентаций. Мы начнем с создания первого слайда нашей презентации. Для этого создайте файл HTML внутри папки views.

 <!-- views/index.html --> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Revealer - Reveal.js multiplexer</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <link rel="stylesheet" href="components/reveal.js/css/reveal.min.css"> <link rel="stylesheet" href="components/reveal.js/css/theme/default.css" id="theme"> </head> <body> <div class="reveal"> <div class="slides"> <section> <h1>Revealer</h1> <h3>Reveal.js multiplexer</h3> </section> </div> </div> <script src="components/reveal.js/js/reveal.min.js"></script> <script type="text/javascript"> Reveal.initialize({history: true}); </script> </body> </html> 

Это самый базовый HTML-код, который нам необходим для начала работы с reve.js. Здесь мы включили файлы Reveal.js CSS и JavaScript. Reveal.initialize() сделает приведенный выше HTML- Reveal.initialize() презентацией. Любой раздел внутри div со slides класса будет действовать как слайд.

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

 var express = require('express') , http = require('http') , path = require('path') , app = express(); app.configure(function(){ app.use(express.static(path.join(__dirname, 'public'))); }); app.get('/', function(req, res){ res.sendfile(__dirname + '/views/index.html'); }); var server = http.createServer(app).listen(3000, function(){ console.log("Express server listening on port 3000"); }); 

Первые несколько строк требуют необходимых зависимостей для нашего сервера, а затем создают объект Express. Следующая строка настраивает общую папку как статический каталог, где сервер будет искать запросы к статическим файлам. Затем мы добавляем маршрут для обслуживания файла index.html и запускаем сервер.

Теперь мы можем увидеть презентацию в браузере, используя http: // localhost: 3000 / url. Но это не то, что нам действительно нужно. Нам нужно, чтобы эта презентация была мультиплексирована, чтобы при смене слайда одним пользователем она отображалась в браузере другого пользователя.

Далее мы установим и настроим модуль Socket.io для включения двунаправленной связи с помощью Websockets.

 $ npm install socket.io --save 

После завершения установки мы готовы включить веб-сокеты на нашем сервере презентаций. Сначала требуется библиотека socket.io в файле app.js, добавив следующую строку в разделе объявления переменных.

 var io = require(“socket.io”); 

Теперь нам нужно передать ранее созданный нами экспресс-сервер в socket.io, а затем указать серверу отправить приветственное сообщение при подключении нового клиента.

 io.listen(server); io.sockets.on('connection', function (socket) { socket.emit("message", "Welcome to Revealer"); }); 

Сервер может отвечать клиентам, когда они подключены. В приведенном выше коде функция обратного вызова для события подключения принимает сокет клиента в качестве аргумента и отправляет приветственное сообщение обратно клиенту.

Давайте перейдем к клиентскому JavaScript, который будет подключаться к этому серверу. Для начала нам нужно включить клиентскую библиотеку socket.io в наш HTML.

 <script src="/socket.io/socket.io.js"></script> 

Далее мы подключимся к созданному нами серверу Websocket.

 var socket = io.connect("http://localhost:3000"); socket.on("message", function(data){ console.log(data); }); 

io.connect подключится к серверу по указанному URL. После подключения мы знаем, что наш сервер ответит приветственным сообщением, которое мы вошли в консоль.

Теперь, когда наш клиент и сервер готовы, и мы можем перейти к реальным вещам. Когда докладчик меняет слайд, он должен уведомить сервер об обновлении всех других клиентов.

 notifyServer = function(event){ data = { indexv : Reveal.getIndices().v, indexh : Reveal.getIndices().h, indexf : Reveal.getIndices().f || 0 } socket.emit("slidechanged" , data); } Reveal.addEventListener("slidechanged", notifyServer); Reveal.addEventListener("fragmentshown", notifyServer); Reveal.addEventListener("fragmenthidden", notifyServer); 

Когда происходит изменение слайда, Reveal.js отправляет событие slidechanged . В случае фрагментов слайда он создает событие fragmentshown или fragmenthidden . Мы обрабатываем все эти случаи здесь, и когда такое событие происходит, оно вызывает notifyServer обратного вызова notifyServer . В любой момент времени Reveal.getIndices() возвращает текущие позиции слайда — горизонтальный, вертикальный и индекс фрагмента. Когда notifyServer функция notifyServer она notifyServer позиции слайдов в объект данных. Затем клиент slidechanged на сервер slidechanged событие вместе с созданными данными.

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

 socket.on("slidechanged", function(data){ socket.broadcast.emit("slidechanged", data); }); 

socket.broadcast.emit отправит данные всем клиентам, кроме отправителя. Таким образом, здесь, когда сервер получает событие slidechanged , он просто перенаправляет данные слайда всем другим клиентам.

Клиент также должен обработать это slidechanged событие, пересылаемое сервером, путем перехода к соответствующему слайду или фрагменту. Для этого на стороне клиента добавьте

 socket.on('slidechanged', function (data) { Reveal.slide(data.indexh, data.indexv, data.indexf); }); 

Reveal.slide() принимает три аргумента: горизонтальный индекс, вертикальный индекс и индекс фрагмента, которые будут иметь значение в случае событий fragmentshown или fragmenthidden .

Добавление безопасности

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

 var masterUser = 'username' , masterPass = 'password'; // Authentication var auth = express.basicAuth(masterUser, masterPass); app.get('/', auth, function(req, res){ res.sendfile(__dirname + '/views/master.html'); }); app.get('/client', function(req, res){ res.sendfile(__dirname + '/views/client.html'); }); 

Теперь, когда пользователь запрашивает маршрут «/», браузер запрашивает учетные данные для аутентификации. express.basicAuth создает промежуточное программное обеспечение для базовой аутентификации, которое мы передали в маршрут «/». Если логин успешный, он отправит master.html. Другие пользователи могут использовать маршрут «/ client» для просмотра презентации, в которую мы не будем отправлять события смены слайдов на сервер.

Полный код теперь будет выглядеть следующим образом.

 // server var express = require('express') , http = require('http') , path = require('path') , ioServer = require('socket.io') , app = express() , masterUser = 'username' , masterPass = 'password'; app.configure(function(){ app.use(express.static(path.join(__dirname, 'public'))); }); // Authentication var auth = express.basicAuth(masterUser, masterPass); app.get('/', auth, function(req, res){ res.sendfile(__dirname + '/views/presentation.html'); }); app.get('/client', function(req, res){ res.sendfile(__dirname + '/views/client.html'); }); var server = http.createServer(app).listen(3000, function(){ console.log("Express server listening on port 3000"); }); var io = ioServer.listen(server); io.sockets.on('connection', function (socket) { socket.emit("message", "Welcome to Revealer"); socket.on("slidechanged", function(data){ socket.broadcast.emit("slidechanged", data); }); }); //client (function(){ var host = 'http://localhost:3000', , socket = io.connect(host); Reveal.initialize({ history: true }); /** start - only in master.js **/ notifyServer = function(event){ data = { indexv : Reveal.getIndices().v, indexh : Reveal.getIndices().h, indexf : Reveal.getIndices().f || 0 } socket.emit("slidechanged" , data); } // listeners for slide change/ fragment change events Reveal.addEventListener("slidechanged", notifyServer); Reveal.addEventListener("fragmentshown", notifyServer); Reveal.addEventListener("fragmenthidden", notifyServer); /** end - only in master.js **/ // Move to corresponding slide/ frament on receiving // slidechanged event from server socket.on('slidechanged', function (data) { Reveal.slide(data.indexh, data.indexv, data.indexf); }); })(); 

Вы можете найти весь исходный код на Github .

Резюме

В этой статье мы увидели, как создать простую презентацию Reveal.js, которой может управлять более одного пользователя. Здесь мы использовали библиотеку Socket.IO для обновления всех подключенных клиентов в режиме реального времени. Мы также добавили базовую защиту для предотвращения контроля презентации неавторизованными пользователями.

Вы можете добавить больше функций и использовать такие технологии, как WebRTC, чтобы сделать его более вездесущим, поэтому я надеюсь, вы увидите, что эта статья — только начало.