はじめに
現在、私は入江開発室という、開発者の集まるオンラインサロン(?)に所属しています。
サロンにはSlackチームがあって、その中に # 朝活で自分の時間をつくろう という名前の、朝早起きしたらメッセージを投稿するchannelがあります。
基本的に「おはようございます!」と投稿するだけですが、不思議と 朝起きるための力をもらえるようなchannelです。
私はこのchannelをとても気に入っているので、早起き人口を増やすためにも、このchannelの動向を可視化するためのwebアプリを作りはじめました。
作っているアプリ
このアプリでは、
- 縦軸 = メッセージ投稿時刻
- 横軸 = 直近2週間の日付
の二軸に対してSlackのメッセージとユーザー情報を紐づけマッピングしています。
マウスオーバーするとメッセージが表示されます。
触ってみたい人はこちら↓
morning | 朝活を応援
縦軸を時刻にする
早速ですが、タイトルに記載した実装方法を紹介します。
全体のコードが見たい方はGithub からどうぞ。
対象データ
[
{
"id": 10,
"user": "UE03YQ20H",
"realName": "Kyogo Mochida",
"image24": "https://avatars.slack-edge.com/2019-01-15/523494664179_c52030a5a9f22b1393b8_24.png",
"text": "おはようございます!",
"msPass": 75988227,
"date": "2019-02-07T15:00:00.000Z"
},
{
"id": 19,
"user": "UE03YQ20H",
"realName": "Kyogo Mochida",
"image24": "https://avatars.slack-edge.com/2019-01-15/523494664179_c52030a5a9f22b1393b8_24.png",
"text": "おはようございます!寝坊した...",
"msPass": 79603223,
"date": "2019-02-05T15:00:00.000Z"
},
{
"id": 27,
"user": "UE03YQ20H",
"realName": "Kyogo Mochida",
"image24": "https://avatars.slack-edge.com/2019-01-15/523494664179_c52030a5a9f22b1393b8_24.png",
"text": "おはようございます",
"msPass": 75439218,
"date": "2019-02-04T15:00:00.000Z"
}
]
各プロパティの説明
- id … データ1件のユニークなID
- user… SlackのユーザーID
- realName…Slackのユーザー名
- image24…Slackのユーザーアイコン
- text…メッセージ内容
- msPass…メッセージの投稿時刻(ミリ秒単位)
- date…メッセージの投稿日
今回は、
msPassとdate だけ気にしていればokです。
msPassはY軸、dateはX軸になります。
msPassは、サーバーサイド(Node.js)で、やや複雑な加工をしているので説明します。
Slack APIを利用してメッセージを取得すると、
レスポンスの形式は下記のようになります。
{
"client_msg_id": "64431F4D-960B-4EB3-8ABF-58D14D26C93E",
"type": "message",
"text": "おはようございます!",
"user": "UBBJW8MNV",
"ts": "1549747882.003100"
},
このts
がmsPassの元になります。
ts
は、UNIXTIMESTAP(秒単位)です。
なので、 ts
に1日の秒数を剰余演算することで、00:00からの経過時間を取得することができます。(分かりにくいので下の図で説明)
Y軸となるmsPassが上記によって求められたらあとは簡単です。
d3のScaleTime で時刻に変換して表示しましょう
const objY = 'msPass';
const yScale: ScaleTime<number, number> = d3.scaleTime();
yScale.domain(d3.extent(data, (d) => +d[objY]));
yScale.range([margins.top, height - margins.bottom])
const yAxis: Axis<{}> = d3.axisLeft(yScale);