Help us understand the problem. What is going on with this article?

聴衆者の力を借りてイベントを盛り上げよう

More than 1 year has passed since last update.

#デモ(2018/12/28追記)
IBM Cloud Kubernetes Serviceに、今回作成したアプリケーション(dockerコンテナ)をデプロイ・公開してみました。(無料枠利用の制約で、2019年1月末までの期間限定公開)

Live Tweeeets Sender(つぶやき送信画面)
http://live-tweeeets-lt.tk

Live Tweeeets Viewer(つぶやき表示画面)
http://live-tweeeets-lt-view.tk

はじめに

プレゼンテーションやパネルディスカッション、ライトニングトークなどのイベントで、聴衆者のつぶやきをスクリーンに表示しているイベントがありますが、結構盛り上がりますよね。聴衆者のリアルタイムなつぶやきが面白かったり、発表者の意見よりも聴衆者のつぶやきの方に共感したりして。
そんな聴衆者参加型のイベントをいつでも気軽にできたらいいなと思い、非常に質素なシンプルな聴衆者のつぶやきを表示するアプリを作ってみました。

アプリケーション(Live Tweeeets)の概要

つぶやき内容が表示される画面をスクリーンに表示しておき、聴衆者がスマホやPCのブラウザを利用してつぶやきを入力・送信すると、聴衆者のつぶやきがスクリーンに表示されます(15秒間)。

利用イメージ
image.png

Live Tweeeets Sender(つぶやき送信画面)
image.png

Live Tweeeets Viewer(つぶやき表示画面)
image.png

アーキテクチャ概要

Docker Hub上のNode-Redコンテナをベースにして、今回のLive Tweeeetsアプリケーションを作りました。作成したアプリケーションはDockerコンテナ化し、Docker Hubに公開しています。
image.png

Docker Hubのリンクです。
https://hub.docker.com/r/has2y/live-tweeeets/

作成したNode-Redフローです。
image.png

[{"id":"9567d52f.9d38d8","type":"http in","z":"2a5fa454.4d923c","name":"","url":"/lt","method":"get","swaggerDoc":"","x":90,"y":180,"wires":[["e36cbeee.f3191"]]},{"id":"e36cbeee.f3191","type":"template","z":"2a5fa454.4d923c","name":"live tweeeets client","field":"payload","fieldType":"msg","syntax":"mustache","template":"<head>\n    <title>Live Tweeeets</title>\n\n    <meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\" />\n</head>\n\n<body>\n    <div class=\"content\">\n        <div id=\"title\"><br>Live Tweeeets</div>\n        <br>\n        <input type=\"button\" id=\"send_btn\" value=\"Send your tweet\" onclick=\"sendMessage()\">\n        <br>\n        <input type=\"text\" id=\"message\" placeholder=\"Please input any tweet(^^)/\" />\n        <div class=\"guide\">\n          <br>[Usage]\n          <br>After inputting your tweet and pressing the \"Send your tweet\" button, your tweet will be displayed for 15 seconds.\n        </div>\n    </div>\n</body>\n\n<script type=\"text/javascript\">\n    var wsUri = \"ws://{{req.headers.host}}/ws/lt\";\n    var ws;\n    ws = new WebSocket(wsUri);\n    ws.onclose = onClose;\n\n    function onClose(e) {\n//        alert(\"WebSocketの接続が切れました。再接続します。\");\n        ws = null;\n        ws = new WebSocket(wsUri);\n        ws.onclose = onClose;\n    }\n\n    function sendMessage() {\n        var message = document.getElementById('message');\n\n        var payload = {\n            message: message.value\n        };\n\n        ws.send(JSON.stringify(payload));\n        \n        message.value = \"\";\n    };\n\n</script>\n\n<style type=\"text/css\">\n* {\n        font-family: 'Quicksand', sans-serif;\n        font-size: 24px;\n    }\n    html,\n    body {\n        margin: 0;\n        padding: 0;\n        height: 100%;\n        background-color: #FFFFFF;\n        margin : 0 10 0 10px ; \n    }\n    #title {\n        text-align: center;\n        font-family: 'Quicksand', sans-serif;\n        color: #107FC9;\n    }\n    #send_btn {\n        width: 100%;\n        right: 0;\n        margin: 0;\n        border: 0;\n        color: #fff;\n        -webkit-appearance: none;\n        border-radius: 0;\n        background-color: #79ceed;\n        display: inline-block;\n    }\n    #message {\n        background-color: #fff;\n        width: 100%;\n    }\n    .guide {\n        color: #152935;\n    }\n    .content {\n        padding-top: 4px;\n        position: relative;\n        width: 100%;\n    }\n}\n</style>","x":310,"y":180,"wires":[["419d88a1.db7238"]]},{"id":"419d88a1.db7238","type":"http response","z":"2a5fa454.4d923c","name":"","x":510,"y":180,"wires":[]},{"id":"c2f51532.106d68","type":"http in","z":"2a5fa454.4d923c","name":"","url":"/lt/view","method":"get","swaggerDoc":"","x":105,"y":260,"wires":[["654cbe30.6743f"]]},{"id":"654cbe30.6743f","type":"template","z":"2a5fa454.4d923c","name":"live tweeeets viewer","field":"payload","fieldType":"msg","syntax":"mustache","template":"<html>\n\n<head>\n    <meta name=\"viewport\" content=\"width=320, initial-scale=1\">\n    <title>Live Tweeeets</title>\n</head>\n\n<body>\n</body>\n</html>\n\n<script type=\"text/javascript\" src=\"//code.jquery.com/jquery-2.0.3.min.js\"></script>\n<script type=\"text/javascript\">\n    var wsUri = \"ws://{{req.headers.host}}/ws/lt\"\n    var ws;\n    ws = new WebSocket(wsUri);\n    ws.onclose = onClose;\n    ws.onmessage = onMessage;\n    var count = 0;\n\n    function onClose(e) {\n//        alert(\"WebSocketの接続が切れました。再接続します。\");\n        ws = null;\n        ws = new WebSocket(wsUri);\n        ws.onclose = onClose;\n        ws.onmessage = onMessage;\n    }\n\n    function onMessage (ev) {\n        count = count + 1;\n        var divid = count;\n\n        var payload = JSON.parse(ev.data);\n        if (payload.message != \"\") {\n            var left = Math.floor(Math.random() * (window.innerWidth - 500 - 50) + 50);\n            var top = Math.floor(Math.random() * (window.innerHeight - 150 - 50) + 50);\n            var div = \"<div id=\\\"\" + divid + \"\\\" class=\\\"tweeeet\\\" style=\\\"position:absolute; top:\" + top + \"px; left:\" + left + \"px;\\\">\" + escapeHtml(payload.message) + \"</div>\";\n            $('body').append(div);\n\n            setTimeout(function () {\n                $('#' + divid).remove();\n            }, 15000);\n\n        }\n        \n    }\n    \n    function escapeHtml(str) {\n        str = str.replace(/&/g, '&amp;');\n        str = str.replace(/</g, '&lt;');\n        str = str.replace(/>/g, '&gt;');\n        str = str.replace(/\"/g, '&quot;');\n        str = str.replace(/'/g, '&#39;');\n        return str;\n    }\n</script>\n<style type=\"text/css\">\n    body {\n        background-color: black;\n        background-size: contain100% 100%;\n        overflow: hidden;\n    }\n    .tweeeet {\n        font-size: 4vw;\n        position: relative;\n        display: inline-block;\n        padding: 0 30px;\n        width: auto;\n        min-width: 230px;\n        height: 80px;\n        line-height: 68px;\n        text-align: center;\n        z-index: 0;\n        color: #F6F6F6;\n    }\n</style>\n\n","x":320,"y":260,"wires":[["497bdf36.cd9d2"]]},{"id":"497bdf36.cd9d2","type":"http response","z":"2a5fa454.4d923c","name":"","x":510,"y":260,"wires":[]},{"id":"74a8ede3.728ac4","type":"websocket in","z":"2a5fa454.4d923c","name":"","server":"1edeb26e.675dfe","client":"","x":100,"y":80,"wires":[["484639c5.9ea718"]]},{"id":"484639c5.9ea718","type":"function","z":"2a5fa454.4d923c","name":"send msg","func":"delete msg._session;\nreturn msg;\n\n","outputs":1,"noerr":0,"x":300,"y":80,"wires":[["4591dcda.6c1244"]]},{"id":"4591dcda.6c1244","type":"websocket out","z":"2a5fa454.4d923c","name":"","server":"1edeb26e.675dfe","client":"","x":500,"y":80,"wires":[]},{"id":"1edeb26e.675dfe","type":"websocket-listener","z":"","path":"/ws/lt","wholemsg":"false"}]

アプリケーションの利用準備

  1. Dockerコンテナの実行環境を準備する ※この記事では省略します

  2. 以下Dockerコマンドで、Dockerコンテナを実行する(だけ)。

docker run -it -p 80:1880 has2y/live-tweeeets

アプリケーションの使い方

1.PCブラウザで以下URLにアクセスして、つぶやき表示画面を表示する

http://server-ip-address/lt/view

2.スマホ or PCブラウザで以下URLにアクセスして、つぶやきを入力・送信する

http://server-ip-address/lt

image.png

3.つぶやき表示画面に、聴衆者のつぶやきが表示される
image.png

まとめ

このアプリケーションは、Cloud上のDockerコンテナの実行環境があれば、5分で利用できるようになります。
今、あなたが企画しているイベント、聴衆者の力を借りてもっと盛り上げてみませんか?

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした