node.js + express + socket.io でスライドショーのシンクロアプリを作成

概要

複数デバイス間でスライドを同期する方法はないか・・・という話があったので、
node.js + express + socket.ioを使って、スライドショーの同期アプリを作ってみた。

こんな感じで左の画面でスライドを変更すると、右の画面も同期して自動的にスライドが変わる。
f:id:yuriken27:20150301222506j:plain

タブレットを想定していたので、Webアプリにして各種ブラウザで実行できる様にした。

デモサイトはこちら

SyncSlideTest

表示のみで操作できないバージョンはこちら
SyncSlideTest

スライドショーのライブラリを選定

スライドショーのライブラリは以下を使用。


Supersized - Full Screen Background Slideshow jQuery Plugin

細かい設定ができて使いやすい。

各種バージョン

node.js :0.10.36
express : 4.11.2
socket.io : 1.3.4

expressでプロジェクト作成

テンプレートはejsを使うため、「-e」を追加して実行

$ express -e slide_sync

   create : slide_sync
   create : slide_sync/package.json
   create : slide_sync/app.js
   create : slide_sync/public
   create : slide_sync/public/images
   create : slide_sync/public/javascripts
   create : slide_sync/public/stylesheets
   create : slide_sync/public/stylesheets/style.css
   create : slide_sync/routes
   create : slide_sync/routes/index.js
   create : slide_sync/routes/users.js
   create : slide_sync/views
   create : slide_sync/views/index.ejs
   create : slide_sync/views/error.ejs
   create : slide_sync/bin
   create : slide_sync/bin/www

   install dependencies:
     $ cd slide_sync && npm install

   run the app:
     $ DEBUG=slide_sync:* ./bin/www

[package.json]にsocket.ioの定義を追加

{
...

  "dependencies": {
...
    "serve-favicon": "~2.2.0",
    "socket.io": "~1.3.4"
  }
}

プロジェクトフォルダに移動してインストールを実行

$ cd slide_sync/
$ npm install

app.jsの編集

app.jsに以下を追加

// サーバモジュール作成
var server = require('http').Server(app);
var io = require('socket.io')(server);

var port = process.env.PORT || 3000;
server.listen(port);


// スライド操作関連
var current_slide = 0;  // 現在のスライド番号を保持

//クライアントから接続があった時
io.sockets.on('connection', function (socket) {

  // コネクションが確立されたら'connected'メッセージを送信する
  console.log("[connection] has received current_slide:[" + current_slide + "]");
  socket.emit('connected', {value: current_slide});

  // メッセージ送信(送信者にも送られる)
  socket.on("C_to_S_message", function (data) {
    console.log("[C_to_S_message] has received");
    current_slide = data.value;
    io.sockets.emit("S_to_C_message", {value: current_slide});
  });

  // ブロードキャスト(送信者以外の全員に送信)
  socket.on("C_to_S_broadcast", function (data) {
    console.log("[C_to_S_broadcast] has received");
    current_slide = data.value;
    socket.broadcast.emit("S_to_C_message", {value: current_slide});
  });

  // 切断したときに送信
  socket.on("disconnect", function () {
    console.log("[disconnect] has received");
  });
});

スライドhtmlを変更

supersizedライブラリの[slide.html]をベースに、views/index.ejsを作成。

サーバとのやりとり関連の処理を追加

<script type="text/javascript">

var s = io.connect('http://young-hollows-5254.herokuapp.com'); //heroku
// var s = io.connect('http://localhost:3000'); //ローカル

//サーバから受け取るイベント
s.on("connect", function () {});  // 接続時
s.on("connected", function (data) {
  addMessage(data.value);
});  // 接続時
s.on("disconnect", function (client) {});  // 切断時
s.on("S_to_C_message", function (data) {
  addMessage(data.value);
});

//クライアントからイベント送信(イベント名は自由に設定できます)
function sendMessage(slide_index) {
  s.emit("C_to_S_message", {value: slide_index}); //サーバへ送信
}

function sendBroadcast(slide_index) {
  s.emit("C_to_S_broadcast", {value: slide_index}); // サーバへ送信
}

//jqueryでメッセージを追加
function addMessage (value,color,size) {
  api.goTo(value + 1);
}

</script>

ページ切り替えの時にサーバとの通信を行う。

<!--Arrow Navigation-->
<a id="prevslide" class="load-item" onclick="click_prevslide();"></a>
<a id="nextslide" class="load-item" onclick="click_nextslide();"></a>
function click_prevslide() {
  var slide_num = $.supersized.vars.options.slides.length;
  sendMessage( ( ($.supersized.vars.current_slide - 1 + slide_num) % slide_num ) );
}

function click_nextslide() {
  var slide_num = $.supersized.vars.options.slides.length;
  sendMessage( ( ($.supersized.vars.current_slide + 1 + slide_num) % slide_num ) );
}

herokuにデモサイドをアップロード

heroku用の実行コマンドファイル[Procfile]を作成

[Procfile]を作成

web: node app.js

herokuにアップロード

$ heroku create
$ git add .
$ git commit -m "first commit"
$ git push heroku master