LoginSignup
0
1

More than 1 year has passed since last update.

TypeScriptを用いたデータ可視化におすすめのライブラリとその使い方

Last updated at Posted at 2023-01-20

概要

データ可視化に使えるJSライブラリはたくさんありますが、TypeScriptでの導入方法に関する情報がまとまったサイトがないので書きました。

紹介するライブラリ一覧

ライブラリ 公式HP 概要
D3.js https://d3js.org/ 言わずと知られた情報可視化ライブラリです。さまざまなチャートを高い自由度で作成できます。まずはギャラリー (https://d3-graph-gallery.com/index.html) をみてみて下さい。
Three.js https://threejs.org/ 3D表現をできるライブラリです。
day.js https://day.js.org/ 時刻データを扱うことに特化したライブラリです。JavascriptのDate型よりも遥かに扱いやすく重宝します。
chroma.js https://gka.github.io/chroma.js/ 色を扱うことに特化したライブラリです。色はデータ可視化において重要な要素ですので必須なライブラリです。

D3.js

言わずと知られた情報可視化ライブラリです。さまざまなチャートを高い自由度で作成できます。まずはギャラリー (https://d3-graph-gallery.com/index.html) をみてみて下さい。

インストール

npm i -S @types/d3 d3

サンプル

スクリーンショット 2023-01-19 18.35.53.png
データの出展:https://www.mhlw.go.jp/stf/covid-19/open-data.html

main.ts

import * as d3 from 'd3';

window.addEventListener('load', () => {
    init();
}, false);

const width: number = 600;
const height: number = 400;
const margin = {
    top : 50, right: 50, bottom: 100, left: 50
};

function init(): void {
    // データの読み込み
    d3.csv('data.csv')
        .then((data) => {
            draw(data);
        })
        .catch((error) => {
            console.log(error)
        });
}


function draw(data: d3.DSVRowArray): void {

    let chartWidth: number = width - margin.left - margin.right;
    let chartHeight: number = height - margin.top - margin.bottom;

    // SVGの設定
    const svg: any = d3.select('body')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    console.log(svg);

    // x axis
    let xScale: any = d3.scaleTime()
        .domain(<Date[]>d3.extent(data, (d: d3.DSVRowString) => new Date(String(d.Date)) ))
        .range([0, chartWidth]);
    svg.append('g')
        .attr('transform', `translate(${margin.left}, ${Number(margin.top + chartHeight)})`)
        .call(d3.axisBottom(xScale).tickFormat(<any>d3.timeFormat('%Y/%m/%d')) )
        .selectAll('text')
        .attr('transform', 'translate(25, 35)rotate(60)');


    // y axis
    let yScale: any = d3.scaleLinear()
        .domain([ 0, Number(d3.max(data, (d: d3.DSVRowString) => +Number(d.ALL) )) ])
        .range([chartHeight, 0]);
    svg.append('g')
        .attr('transform', `translate(${margin.left}, ${margin.top})`)
        .call(d3.axisLeft(yScale));


    // 折線
    const line: any = d3.line()
        .x((d: any) => xScale(new Date(String(d.Date))))
        .y((d: any) => yScale(Number(d.ALL)));

    // 描画
    svg.append('path')
        .datum(data)
        .attr('transform', `translate(${margin.left}, ${margin.top})`)
        .attr('fill', 'none')
        .attr('stroke', 'steelblue')
        .attr('stroke-width', 1.5)
        .attr('d', line);
}
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="main.js"></script>
    <title>Line Chart</title>
</head>
<body>
</body>
</html>

three.js

3D表現をできるライブラリです。

インストール

npm i -S three @types/three

サンプル

スクリーンショット 2023-01-20 11.30.32.png

main.ts

import * as THREE from "three";

window.addEventListener('load', () => {
    init();
}, false);


let cvsWidth: number = 600;
let cvsHeight: number = 600;
let renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ alpha: true });
let scene: THREE.Scene = new THREE.Scene();
let camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(50, cvsWidth / cvsHeight, 1, 2000);
let cube: THREE.Mesh;

function init() {
    let elem = <HTMLElement>document.querySelector('body');
    elem.append(renderer.domElement);
    camera.position.set(50, 50, 50);
    camera.lookAt(new THREE.Vector3(0, 0, 0));
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(cvsWidth, cvsHeight);
    camera.aspect = cvsWidth / cvsHeight;
    camera.updateProjectionMatrix();

    const light = new THREE.DirectionalLight(0xffffff);
    light.position.set(1, 1, 1);
    scene.add(light);

    const axes = new THREE.AxesHelper(10);
    scene.add(axes);

    draw();
    render();
}

function render() {
    requestAnimationFrame(render);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
}

function draw() {
    const geometry = new THREE.BoxGeometry(10, 10, 10);
    const material = new THREE.MeshLambertMaterial({
        color: new THREE.Color('#4da9ff'),
        transparent: true,
        opacity: 0.5
    });
    cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="main.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #222;
        }
    </style>
    <title>Document</title>
</head>
<body>
</body>
</html>

day.js

時刻データを扱うことに特化したライブラリです。JavascriptのDate型よりも遥かに扱いやすく重宝します。

インストール

npm i -S dayjs

tsconfig.jsonに"esModuleInterop": true,を追加する

{
    "compilerOptions": {
        // ...
        "esModuleInterop": true,
        // ...
    }    
}

サンプル

スクリーンショット 2023-01-20 13.38.27.png

main.ts

import dayjs, { Dayjs } from 'dayjs';
// UTCを使うためのおまじない
import utc from "dayjs/plugin/utc";
dayjs.extend(utc);
// タイムゾーンを使うためのおまじない
import timezone from "dayjs/plugin/timezone";
dayjs.extend(timezone);

window.addEventListener('load', () => {
    init();
}, false);

function init(): void {
    let time = '2020/06/01 12:13:42';

    let utc0 = dayjs.tz(time, 'UTC');
    let cet0 = dayjs.tz(time, 'CET');
    let jst0 = dayjs.tz(time, 'Asia/Tokyo');
    let utc0Millis = utc0.valueOf();
    let cet0Millis = cet0.valueOf();
    let jst0Millis = jst0.valueOf();
    let utc0Str = utc0.format('YYYY/MM/DD HH:MM:ss');
    let cet0Str = cet0.format('YYYY/MM/DD HH:MM:ss');
    let jst0Str = jst0.format('YYYY/MM/DD HH:MM:ss');
   
    let utc1 = dayjs(time).tz('UTC');
    let cet1 = dayjs(time).tz('CET');
    let jst1 = dayjs(time).tz('Asia/Tokyo');
    let utc1Millis = utc1.valueOf();
    let cet1Millis = cet1.valueOf();
    let jst1Millis = jst1.valueOf();
    let utc1Str = utc1.format('YYYY/MM/DD HH:MM:ss');
    let cet1Str = cet1.format('YYYY/MM/DD HH:MM:ss');
    let jst1Str = jst1.format('YYYY/MM/DD HH:MM:ss');

    console.log('dayjsオブジェクトを生成する際1タイムゾーンを指定する場合')
    console.table([
        ['Time Zone', 'UNIX時間(msec)', '日付'],
        ['UTC', utc0Millis, utc0Str],
        ['CET', cet0Millis, cet0Str],
        ['JST', jst0Millis, jst0Str],
    ]);

    console.log('dayjsオブジェクトを生成したのちに、タイムゾーンを指定する場合')
    console.table([
        ['Time Zone', 'UNIX時間(msec)', '日付'],
        ['UTC', utc1Millis, utc1Str],
        ['CET', cet1Millis, cet1Str],
        ['JST', jst1Millis, jst1Str],
    ]);
}

chroma.js

インストール

npm i -S chroma-js @types/chroma-js

サンプル

スクリーンショット 2023-01-20 17.06.32.png

main.ts

import chroma from 'chroma-js';

window.addEventListener('load', () => {
    init();
}, false);

function init(): void {
    let elem: HTMLElement = <HTMLElement>document.querySelector('body');

    let colorList: { [key: string]: chroma.Color } = {
        'chroma.rgb(235, 64, 52)': chroma.rgb(235, 64, 52),
        'chroma.rgb(235, 64, 52).alpha(0.5)': chroma.rgb(235, 64, 52).alpha(0.5),
        'chroma.hsv(229, 0.78, 0.92)': chroma.hsv(229, 0.78, 0.92),
        'chroma.hsv(229, 0.78, 0.92).darken()': chroma.hsv(229, 0.78, 0.92).darken(),
        'chroma.hsv(229, 0.78, 0.92).brighten()': chroma.hsv(229, 0.78, 0.92).brighten(),
        'chroma.hsv(229, 0.78, 0.92).saturate()': chroma.hsv(229, 0.78, 0.92).saturate(),
        'chroma.hsv(229, 0.78, 0.92).desaturate()': chroma.hsv(229, 0.78, 0.92).desaturate(),
    };


    Object.keys(colorList).forEach(key => {
        let color: chroma.Color = colorList[key];
        let colorElem = document.createElement('span');
        colorElem.className = 'colorPanel';
        colorElem.style.backgroundColor = color.css();
        colorElem.innerText = color.hex();

        let labelElem = document.createElement('span');
        labelElem.innerText = key;

        let div = document.createElement('div');
        div.append(colorElem);
        div.append(labelElem);
        elem.append(div);
    });
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="main.js"></script>
    <title>Document</title>
    <style>
        .colorPanel {
            display: inline-block;
            width: 80px;
            height: 20px;
            margin: 10px;
            padding: 3px 10px 6px 10px;
            text-align: center;
            border-radius: 5px;
            color: #FFF;
        }
    </style>
</head>
<body>
</body>
</html>
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1