読者です 読者をやめる 読者になる 読者になる

UZABASE Tech Blog

株式会社ユーザベースの技術チームブログです。 主に週次の持ち回りLTやセミナー・イベント情報について書きます。

NewsPicks × D3.js

NewsPicksの開発をしている板倉です。

NewsPicksではニュースを見る画面とは別に、
どの記事がどれくらい読まれているかという画面の開発を進めています。
直感的にわかる画面がほしいということで、 D3.jsを使って画面を開発することになりました。
D3.jsを使うにあたって勉強するつもりで何か作ろうと思い書いたのが今回のエントリーになります。

今回の開発環境

Mac OS X(10.10)
D3.js(3.4.13)

D3.jsについて

まずは、D3について少しだけ。
Githubの人気リポジトリに入っている人気のJavaScriptライブラリです。(2014/11 時点)
https://github.com/trending?|=javascript

公式
D3.js 日本語 翻訳
APIリファレンス
チュートリアル

APIリファレンスを見ると、たくさんの機能があるのがわかります。

地図を書いてみよう

APIリファレンスを見ていて気になったのがGeography
ということで日本地図を書いてみました。

f:id:uzabase:20141218133859p:plain

参考にしたサイト
D3.jsとTopoJSONで地図を作る

地図上に何か表示してみよう

地図を描いただけだと面白くないので、地震のデータを使って地図上に表示してみました。
まずは、データの取得。
以下のサイトで日本の緯度経度、地震の大きさと期間を入力してデータをダウンロードしました。

USGS

f:id:uzabase:20141218133910p:plain

ダウンロードしたデータを0.1秒ずつずらして描画してみました。
円をそのままにしておくと画面が円だらけになるので、描画して2秒後に消しています。

d3.csv('geo/eq.csv', function(d) {
    // データが降順だったので反転
    d = d.reverse();
    // 大きさ
    var rScale = d3.scale.linear().domain(d3.extent(d, function(e){
         return e.mag;
    })).range([3, 81]);
    // 深さ
    var colorScale = d3.scale.linear().domain(d3.extent(d, function(e){
         return e.depth;
    })).range(['yellow', 'red']);
    g.selectAll('circle')
         .data(d)
         .enter().append('circle')
         .attr('fill', function(d) { 
              return colorScale(d.depth);
         })
         .attr('fill-opacity', 0.5)
         .attr('stroke-width', '1')
         .attr('stroke', function(d) { 
              return colorScale(d.depth);
         })
         .attr('cx', function(d){
             return projection([Number(d.longitude), Number(d.latitude)])[0];
         })
         .attr('cy', function(d){
             return projection([Number(d.longitude), Number(d.latitude)])[1];
         })
         .transition().delay(function(d, i) { 
              return i * 100;
         })
        .attr('r', function(d) {
             return rScale(d.mag)
         })
        .each('start', function(d){
             dateText.text(df(new Date(d.time)));
             mag.text('M ' + d.mag);
             depth.text('Depth: ' + d.depth + ' km');
         })
        .transition().delay(function(d, i) {
             return (i * 100) + 2000
         })
        .each('end', function(d){
             d3.select(this).remove();
         });
})

実装したものはこちら

数字が並んでるデータを見るだけだと気付きにくいことも
図形で表現してみると新しい発見がありますね。

Uzabaseではデータの視覚化を進めるエンジニアを募集しております。
興味をお持ちいただいた方はWantedlyなどからご連絡ください!