前回、チャットツールを作ってみましたが、デザイン要素が全くなかったので、少しUIにこだわったバージョンにアップデートしてみました。
Node.jsを短期学習してみる #3「チャット」
変更点
- チャットに入った場合と出た場合のユーザーの「入室」「退室」をアイコンにしてみた
- メッセージを、テキスト改行の形式から、LINEチャットみたいな見栄えに変更
- 自分と、他の人を見分けられるように色を変えてみた。
- 自分と、他の人の見分けを位置で左右にワケてみた。
- スマホで見た場合にviewportをセットして、操作しやすくする。
見た目で比べる
旧バージョン
新バージョン
見て分かっていただけると思うが、UIデザインを入れた場合と入れなかった場合は、印象も使い勝手も、格段に違ってくる。
最近は、「UI/UX」というジャンルで、デザイン性もシステムの重要な要素という分野になってきている。
ソースコード
/**
* Lineのようなチャットシステム
*/
// 1.モジュールオブジェクトの初期化
var fs = require("fs");
var server = require("http").createServer(function(req, res) {
res.writeHead(200, {"Content-Type":"text/html"});
var output = fs.readFileSync("./index.html", "utf-8");
res.end(output);
}).listen(1080);
var io = require("socket.io").listen(server);
// ユーザ管理ハッシュ
var userHash = {};
// 2.イベントの定義
io.sockets.on("connection", function (socket) {
// 接続開始カスタムイベント(接続元ユーザを保存し、他ユーザへ通知)
socket.on("connected", function (name) {
userHash[socket.id] = name;
for(var i in userHash){
io.sockets.emit("publish", {mode:"user-add",socket_id:i,name:userHash[i]});
}
});
// メッセージ送信カスタムイベント
socket.on("publish", function (data) {
io.sockets.emit("publish", {mode:"message",socket_id:socket.id,name:data.name,value:data.value});
});
// 接続終了組み込みイベント(接続元ユーザを削除し、他ユーザへ通知)
socket.on("disconnect", function () {
if (userHash[socket.id]) {
delete userHash[socket.id];
io.sockets.emit("publish", {mode:"user-del",socket_id:socket.id});
}
});
});
console.log("Run ...");
<html>
<head>
<meta charset="UTF-8">
<title>Chat</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<style type="text/css">
html,body{
height:100%;
margin:0;
padding:0;
}
/*<<head*/
div.page-head{
position:fixed;
width:100%;
top:0;
left:0;
padding:0;
margin:0;
z-index:100;
}
div.page-head div.users{
text-align:center;
background-color:#EEE;
margin:0px;
height:40px;
padding:0px;
line-height:40px;
}
div.page-head div.comment{
text-align:center;
height:28px;
padding:10px 0 10px 0;
background-color:white;
border-bottom:1px dotted #DDD;
}
div.page-head div.comment input[type="text"]{
width:200px;
height:28px;
border:1px solid #CCC;
border-radius:0;
-webkit-appearance: none;
vertical-align:middle;
margin:0;
padding:4px;
font-size:14px;
}
div.page-head div.comment button{
width:60px;
height:28px;
line-height:20px;
border-radius:0;
-webkit-appearance: none;
border:1px solid #CCC;
background-color:#CCC;
color:white;
font-weight:bold;
margin:0;
padding:4px;
font-size:14px;
vertical-align:middle;
}
/*head>>*/
/*<<user-icon*/
div.user , div.msg-user-other div.msg-user{
background-color:blue;
width:32px;
height:32px;
line-height:32px;
margin:2px 2px 0 0;
padding:0;
text-align:center;
font-size:10px;
color:white;
border:0;
border-radius:16px;
display:inline-block;
overflow:hidden;
}
div.user_my , div.msg-user-my div.msg-user{
background-color:orange;
display:inline-block;
vertical-align:top;
}
/*user-icon>>*/
/*<<message*/
#msg{
width:100%;
max-width:480px;
z-index:10;
margin:100px auto 0 auto;
}
#msg div.msg-user-other{
vertical-align:top;
margin:4px;
position:relative;
display:block;
}
#msg div.msg-user{
text-align:left;
}
#msg div.msg-user-my{
text-align:right;
}
#msg div.msg-value{
position:relative;
max-width:220px;
display:inline-block;
margin:0 10px 10px 10px;
padding:4px 20px;
border-radius:8px;
vertical-align:top;
}
#msg div.msg-user-other div.msg-value{
border:2px solid blue;
background-image:linear-gradient(to bottom,white,#66F);
}
#msg div.msg-user-other div.msg-value:after{
content: '';
position: absolute;
border-right: 10px solid blue;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
top: 10px;
left: -12px;
}
#msg div.msg-user-my div.msg-value{
border:2px solid orange;
background-image:linear-gradient(to bottom,white,orange);
}
#msg div.msg-user-my div.msg-value:after{
content: '';
position: absolute;
border-left: 10px solid orange;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
top: 10px;
right: -12px;
}
/*message>>*/
</style>
</head>
<body>
<div class='page-head'>
<div id="users" class='users'></div>
<div class='comment'>
<input type="text" id="msg_input" style="width:200px;" /><button onclick="publishMessage();">sent</button>
</div>
</div>
<div id="msg"></div>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
// 1.イベントとコールバックの定義
var socketio = io.connect('http://%server-address%:1080');
socketio.on("connected", function(name) {});
socketio.on("publish", function (data){
if(data.mode=="user-add"){
user_add(data.socket_id,data.name,data.people);
}
else if(data.mode=="user-del"){
user_del(data.socket_id);
}
else{
addMessage(data.socket_id,data.name,data.value);
}
});
socketio.on("disconnect", function () {});
// 2.イベントに絡ませる関数の定義
function start(name) {
socketio.emit("connected", name);
}
function publishMessage() {
var textInput = document.getElementById('msg_input');
var msg = textInput.value;
socketio.emit("publish", {name:myName,value: msg});
textInput.value = '';
}
function addMessage (socket_id,name,msg) {
if(msg===""||msg==undefined){return}
var domMeg = document.createElement('div');
var user_icon = "user";
//message-value
var val = "";
if(socket_id == socketio.id){
domMeg.className = "msg-user-my";
user_icon += " user_my";
val += "<div class='msg-value'>"+ msg +"</div>";
val += "<div class='user user_my'>"+ name +"</div>";
}
else{
domMeg.className = "msg-user-other";
val += "<div class='user'>"+ name +"</div>";
val += "<div class='msg-value'>"+ msg +"</div>";
}
domMeg.innerHTML = val;
msgArea.appendChild(domMeg);
}
function user_add (socket_id,name,people) {
if(document.getElementById("user_id_"+socket_id)!=null){
return;
}
var users = document.getElementById("users");
if(users==null){return}
//エレメント作成
var div = document.createElement("div");
if(socket_id == socketio.id){
div.className = "user user_my";
}
else{
div.className = "user";
}
div.id = "user_id_"+socket_id;
div.innerHTML = name
users.appendChild(div);
}
function user_del (socket_id) {
var user = document.getElementById("user_id_"+socket_id);
if(user!=null){
user.parentNode.removeChild(user);
}
}
// 3.開始処理
var msgArea = document.getElementById("msg");
var myName = Math.floor(Math.random()*100)+1;
start(myName);
</script>
</body>
</html>
注意点
「%server-address%」の箇所はサーバーのIPアドレスかドメインで書き換えてください。
起動
# 通常起動
$ node chat.js
# 永久起動
$ forever start chat.js
# アクセスURL
# http://%server-address%:1080/
実際に使ってみる
既にforeverで立ち上げっぱなしにしているので、興味のある人は試してもらいたい。
http://chat.ideacompo.com:1080/
※すみません、現在停止してます。
ちなみに、このツールの為に、サブドメインと、リバースプロキシの設定を施して、自宅サーバーの裏に置いてあるraspberry-piで動かしている。
本当なら、同時に何人ぐらいでアクセスできるか試したいのだが、それは別の機会で行うことにしよう。
まだイケていないトコロ
入室した人を乱数でナンバリングして、それをそのまま名前にしているので、ログインという機能で、名前を入力できる機能をつけなければいけない。
できれば、twitterなどのOAuth認証で、アイコンを取得してくると、ユーザーが画像になって非常にUI的に良くなるイメージがある。
だんだんサービスみたいになってきたな・・・
次回、そこを改修してFIXしたいと思う。
0 件のコメント:
コメントを投稿