BLOG

ブログ

Nuxt上でのd3を利用した散布図の作成方法

背景

 横断的にゲーミングPCを比較検討するサイトがないなと感じたことをきっかけに、散布図的にパソコンを比較検討できるサイトを作ろうと思ったのが始まりでした。 サイトのイメージやテーブル設計はスラスラと出来上がったもののjavascriptでクリック可能な散布図を作ろうと思った時に意外といいものが見つからず、最終的にたどり着いたのがd3.jsでした。 後々知ったのですがd3.jsは古くからあるライブラリでNuxtの利用事例はそこまで見当たらなかったですが、 githubのスターはとても多くとても優れたライブラリのようですね。
 今回はそんなd3を利用して散布図を書いてみる方法についてまとめてみようと思います。

完成物

ゲーミングサーチ(現在は閉鎖)

 サイト自体は細かい箇所を修正中(2021/10/29)なのですが、散布図自体は完成しいい感じにできています。

インストール

  1. npm install d3 --save
  2. build: { standalone: true, } を nuxt.config.js に追記する
  3. import * as d3 from "d3"; 利用したいページやコンポーネントの中でimportする

※環境によって変わる可能性がありますが、手準2を行わないと色々とエラーが出てしまうので注意してください。

設計

DOM構成

 d3は

d3
  .select('#chart')
  .append('svg')
  .attr('wid...

といった形で、 DOM構成をjavascript上で追加していくことができるライブラリとなっています。 つまり散布図の場合は「グラフを書く」と言うよりも「グラフになるように点や線を指定箇所に置いていく」といった感覚に近いものを感じました。 (x軸・y軸はそれっぽい感じに描いてくれる関数があるので全ての位置を指定していくわけではないです)


 ちなみにchart.jsなどを利用していた私にとってはこのDOMで作っていくイメージが掴めず結構苦労をしたので、 最初にd3のサンプルコードを読み込んでDOMをどのように作っていくかを学ぶのがお勧めかと思います。

クリックやマウスオーバー

d3がDOMを作りイベントやattributeを好きに追加できるため、 クリックイベントなどはほぼ自由になんでも加えることができる状況でした。 いくつか案はあったのですがひとまず以下のような機能を追加しました。

  • onclickイベントを各ポイントに追加(PCの詳細モーダルが表示される)
  • mouseoverイベントを各ポイントに追加(名前が濃く表示される)
  • 右下の会社ラベルにmouseoverイベントを追加(対象データだけが濃く出るようになっている)

三つ目は参考にしたサイトで使っていたのでそのまま入れた節はありますが、 基本的にグラフ上の情報はなるべく落として見やすさを向上させるために使っています

開発

DOM構成

 基本的には以下のような関数を繋げる形で構成を作っていきます。

関数説明
.selectDOMの特定要素を取得.select('#chart')
.append特定要素の中に要素を追加.append('svg')
.attr特定要素にattributionを追加.attr('width', 300)
.style特定要素にstyleを追加.style('fill', 'gray')
.on特定要素にclickイベントなどを追加.on('click', function (data, elem) { console.log('test') })

 例えば描写部分(DOM構成画像における真ん中のgまで)で言うと以下のように作ることができます。

d3
    .select('#chart')
    .append('svg')
    .attr('width', <em>this</em>.width + <em>this</em>.margin.left + <em>this</em>.margin.right)
    .attr('height', <em>this</em>.height + <em>this</em>.margin.top + <em>this</em>.margin.bottom)
    .append('g')
    .attr('transform', `translate(${<em>this</em>.margin.left},${<em>this</em>.margin.top})`)

クリックやマウスオーバー

 イベントの追加については上記の .on を利用することで好きな場所に入れることができます。 また attr を使うことでclass名などもついかできるため、 クラス名をつけた上でイベント内で以下のような関数を呼び出すことで色の濃さなどを変更することができます。

d3
    .select('.bubbles' + d.id).style('opacity', 1)

vueファイルの概要

<template>
  <div>
    <v-card flat>
      <v-card-title class="text-h6 font-weight-black pb-2"
        >マッピング</v-card-title
      >
      <v-card-text class="pa-0" align="center">
        <div id="chart"></div>
      </v-card-text>
      ...
    </v-card>
  </div>
<template>

<script>
import * as d3 from 'd3'

export default {
    ...
    mounted() {
        this.updateBubble(this.itemSets)
    },
    methods: {
        updateBubble(itemSets) {
            d3.selectAll('svg > *').remove()
            d3.selectAll('svg').remove()
            d3
                .select('#chart')
                .append('svg')
                .attr('width', this.width + this.margin.left + this.margin.right)
                .attr('height', this.height + this.margin.top + this.margin.bottom)
                .append('g')
                .attr('transform', `translate(${this.margin.left},${this.margin.top})`)
            ...
        },
    },
}
</script>

感想

 今回Nuxtjs上でクリックなどできる散布図を作成してみました。ライブラリによってできることできないことが様々かと思いますが、 d3.jsに関してはDOMの構成から行うため設計次第でなんでもできる非常に柔軟性の高いライブラリだと感じました。 「クリックできればいいか」程度に感じていたのですが色々できることがわかったので、

  • 散布図のドットを画像に変えてみる
  • フィルター条件で表示するドットを変える
  • ゲームの必要スペック等の閾値線を追加する

といったことを今後やっていきたいと思います。

参考リンク

SinkCapitalではデータに関する支援を行っています

弊社はスペシャリスト人材が多く在籍するデータ組織です。 データ分析や分析基盤の設計などでお困りの方がいらっしゃれば、 まずは無料で、こちらから各分野のスペシャリストに直接相談出来ます。