Было бы прикольно использовать свой смартфон в качестве пульта управления, не так ли? На самом деле, выглядит не очень то и сложно. Вам даже не нужно уметь писать крупные приложения, так как имеется браузера, поддерживающий открытие сокетов. В этом коротком уроке мы воспользуемся Node.js и Socket.io, чтобы с помощью телефона управлять презентацией, запущенной на компьютере.
Есть множество крутых библиотек HTML5 для создания презентаций, но не одна из них не предусмотрена для задуманной нами идеи. В связи с этим мы воспользуемся Reveal.js — библиотека будет работать с анимацией и реагировать на нажатие клавиатуры или прикосновение к экрану смартфона.
Мы не будем разрабатывать отдельный интерфейс управления. Вместо этого займемся синхронизацией открытой презентации на обоих устройствах. Это позволит вам не только видеть мобильную версии презентации, но и понимать, какой из слайдов активен в данный момент.
Идея
Наша задумка проста — Reveal.js будет передавать номер текущего слайда через URL в виде хеша (например, example.com/#/1). Затем мы будем рассылать данный хеш на все остальные подключенные устройства, что будет перелистывать на них презентации автоматически. В связи с этим любой сможет испортить все элементарным открытием произвольного слайда, что приведет к перелистыванию на всех устройствах. Во избежание сего установим пароль и будем требовать его ввода для подключения.
Полезно упомянуть то, что у Reveal.js уже есть API, и мы можем использовать его для синхронизации, но техника смены и рассылки хеша проще, так что воспользуемся ею.
Наша презентация
Запуск примера
Вы можете запустить пример на своем компьютере или развернуть у провайдера типа Heroku. Первый вариант проще, но нужно установить node.js и npm. Второй подразумевает установку heroku toolbelt и регистрацию в системе.
Для запуска локально:
- Скачайте архив с кодом;
- Убедитесь в том, что node.js установлен;.
- Разархивируйте скачанный файл;
- Откройте терминал и перейдите в папку с извлеченными файлами;
- Запустите
npm install
для установки библиотек; - Запустите приложение командой
node app.js
; - Откройте http://localhost:8080 и введите пароль (“kittens“ по умолчанию);
- Откройте http://<локальный адрес компьютера> на телефоне и введите ту же фразу;
- Радуйтесь!
Для запуска в Heroku:
- Скачайте архив с кодом;
- Разархивируйте его;
- Откройте терминал и перейдите в папку;
- Создайте репозиторий и первый commit;
- Создайте приложение в Heroku;
- Запустите
git push heroku master
; - Откройте приложение по его адресу и введите пароль “kittens” (по умолчанию).
Прочитать больше об этом процесс можно здесь. Если Вы пользуетесь другим провайдером, последние шаги могут отличаться.
Код
Хватит разговаривать, давайте взглянем на код! У нас всего два JavaScript файла – app.js для back-end и script.js для браузера. Вы можете запустить приложение в Node.js 0.10+ или в io.js.
В серверной части мы используем express и socket.io. Его задача — прослушивание событий socket.io и отправка ответов на них. С express.static мы отображаем файлы из публичных папок. В файле public/index.html содержится сама презентация. Она обрабатывается автоматически через express.static, так что в адресе не нужно указывать “/”.
app.js
// This is the server-side file of our mobile remote controller app.
// It initializes socket.io and a new express instance.
// Start it by running 'node app.js' from your terminal.
// Creating an express server
var express = require('express'),
app = express();
// This is needed if the app is run on heroku and other cloud providers:
var port = process.env.PORT || 8080;
// Initialize a new socket.io object. It is bound to
// the express app, which allows them to coexist.
var io = require('socket.io').listen(app.listen(port));
// App Configuration
// Make the files in the public folder available to the world
app.use(express.static(__dirname + '/public'));
// This is a secret key that prevents others from opening your presentation
// and controlling it. Change it to something that only you know.
var secret = 'kittens';
// Initialize a new socket.io application
var presentation = io.on('connection', function (socket) {
// A new client has come online. Check the secret key and
// emit a "granted" or "denied" message.
socket.on('load', function(data){
socket.emit('access', {
access: (data.key === secret ? "granted" : "denied")
});
});
// Clients send the 'slide-changed' message whenever they navigate to a new slide.
socket.on('slide-changed', function(data){
// Check the secret key again
if(data.key === secret) {
// Tell all connected clients to navigate to the new slide
presentation.emit('navigate', {
hash: data.hash
});
}
});
});
console.log('Your presentation is running on http://localhost:' + port);
А вот и JavaScript для front-end, который слушает событие hashchange и отправляет сообщение socket.io на сервер.
public/assets/js/script.js
$(function() {
// Apply a CSS filter with our blur class (see our assets/css/styles.css)
var blurredElements = $('.homebanner, div.reveal').addClass('blur');
// Initialize the Reveal.js library with the default config options
// See more here https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
history: true // Every slide will change the URL
});
// Connect to the socket
var socket = io();
// Variable initialization
var form = $('form.login'),
secretTextBox = form.find('input[type=text]');
var key = "", animationTimeout;
// When the page is loaded it asks you for a key and sends it to the server
form.submit(function(e){
e.preventDefault();
key = secretTextBox.val().trim();
// If there is a key, send it to the server-side
// through the socket.io channel with a 'load' event.
if(key.length) {
socket.emit('load', {
key: key
});
}
});
// The server will either grant or deny access, depending on the secret key
socket.on('access', function(data){
// Check if we have "granted" access.
// If we do, we can continue with the presentation.
if(data.access === "granted") {
// Unblur everything
blurredElements.removeClass('blurred');
form.hide();
var ignore = false;
$(window).on('hashchange', function(){
// Notify other clients that we have navigated to a new slide
// by sending the "slide-changed" message to socket.io
if(ignore){
// You will learn more about "ignore" in a bit
return;
}
var hash = window.location.hash;
socket.emit('slide-changed', {
hash: hash,
key: key
});
});
socket.on('navigate', function(data){
// Another device has changed its slide. Change it in this browser, too:
window.location.hash = data.hash;
// The "ignore" variable stops the hash change from
// triggering our hashchange handler above and sending
// us into a never-ending cycle.
ignore = true;
setInterval(function () {
ignore = false;
},100);
});
}
else {
// Wrong secret key
clearTimeout(animationTimeout);
// Addding the "animation" class triggers the CSS keyframe
// animation that shakes the text input.
secretTextBox.addClass('denied animation');
animationTimeout = setTimeout(function(){
secretTextBox.removeClass('animation');
}, 1000);
form.show();
}
});
});
It’s Slideshow Time!
Наш пульт в виде смартфона готов! Надеюсь, Вам это пригодится и понравится.
Автор: alexandfox
Хотел взять и изучить исходный код, но “403 Forbidden”!! :(
Это не есть хорошо.