見出し画像

【アプリ開発日記44週目】next.jsでローカルcsvを読み込み散布図を作成する

 おはようございます、ちゅーりんです。久しぶりにnextjsを触れると忘れたことが多々あったり、逆に基本的なことにも飛ばしていた発見があったりと、最初の数日間のリハビリを終えて実りの多い時間がやってきました。

 さて本題のCSVですが、これは後半にまわして前半でGoogle認証の実装について軽く触れさせてください。

「あれ、以前書いてたじゃん」

と言われるのも承知の上ですが、恥ずかしい理由があるのです。

 というのも、それから時間も空き、案の定すっかり忘れていたので実装方法を探していたところ……

 検索結果の上位に自分の記事が出てきてしまっていたんですよね。最初に驚き、そして嬉しさが一瞬流れてから冷や汗がたくさん流れました。

 たしかに実装方法について一通りの流れが載っているとはいえ、「models.pyをかく」一行で済ませてしまうなどというかなり大雑把な内容になっていたので、、、

 結果的にこの記事を見てスムーズに実装できたのですが、それはあくまで当時作っていたコードを見れたため。それなしでこの記事を読んでも、全体の概観やイメージ把握には向いているとして、いざ実装となると正直エラーが出てきたらどう対応すべきか分からない場合も多々あると思います……

 そのため、実際に1から作成して動作を確認したコードをGitHubで公開しました。コンセプトは「このReadmeとコードを見れば、プロジェクトの作成から実装までを迷わずできる」です。

 もしこれからNext.jsにGoogle認証を実装される方はこの記事を参考にしていただければ幸いです。わかりにくい所があればご連絡いただけるとありがたいです!

CSVの読み込み

 すいません、本題からだいぶ逸れてしまいましたが、「Next.jsでローカルのCSVを読み込んで配列に直す」処理についてざっと書いていきます。

 とは言っても、プラグインも必要とせず非常にシンプルなので驚くかもしれません、

 私が実装しようとした時に「CSVをアップロードしてその内容を取得する」という記事はたくさんあったのです、画像ファイルのように「publicフォルダ(ローカル)内に配置したCSVを読み込みたい!」という時に少し苦労したため、備忘録としてまとめておきました!

 以下、CSVを配列で出力するコードです。

useEffect(() => {
    fetch(`http://127.0.0.1:3000/csv/{ファイル名}.csv`)
    .then((res) => {
        if(!res.ok) {
            console.log('正常にリクエストを処理できませんでした。');
        }
        return res.text();
    })
    .then((csv_data) => {

        const data_string = csv_data.split('\r\n');

        for (let i = 0; i < data_string.length; i++) {
            data_array[i] = data_string[i].split(',');
            console.log(data_array[i]); // ['2022-06-11', '991116', '284', '17.25', '0']
        }
    })
    .catch((error) => {
        console.log(`エラーが発生しました。\n${error}`);
    })
},[])

 ただ、この処理の欠点として「セル内にカンマ(,)があるとその行がずれて表示される」があります。今回扱ったデータではカンマが入っていないので上記を使っていますが、必要に応じて「data_array[i] = data_string[i].split(',');」の部分を修正して使ってください!

CSVから散布図を作成

 今回はd3.jsを使用します。Reactではどうやって入れるんだろう、と探していましたが、シンプルに

npm install d3
----- graph.js -----

import * as d3 from "d3";
import { useEffect } from "react";

export default function Graph() {

    useEffect(() => {

        (省略)
 
        if (document.getElementById('svg-quiz-sum').innerHTML == '') {

            var width = 300;
            var height = 250;

            var svg = d3.select("body").select('#graph').append("svg").attr("width", width).attr("height", height);
            var padding = 30;

            var time_start = d3.min(data_daily, function(d){return new Date(d[0]);})
            time_start.setDate(time_start.getDate() - 1);
            var time_end = d3.max(data_daily, function(d){return new Date(d[0]);})

            var xScale = d3.scaleTime()                //    X軸(日付)
                .domain([time_start, time_end])
                .range([padding, width - padding]);
            var yScale = d3.scaleLinear()                //    Y軸(データ)
                .domain([0, d3.max(data_daily, function(d){return d[1]*5/4;})])
                .range([height - padding, padding]);

            var xAxis = d3.axisBottom(xScale)
                .ticks(d3.timeDay.every(7))
            var yAxis = d3.axisLeft(yScale);

            svg.append("g")
                .attr("transform", "translate(" + 0 + "," + (height - padding) + ")")
                .call(xAxis)
            svg.append("g")
                .attr("transform", "translate(" + padding + "," + 0 + ")")
                .call(yAxis);

            svg.append("g")
                .selectAll("circle") // 選択した場所<データ数の分は新たに作成
                .data(data_daily)
                .enter()
                .append("circle")
                .attr("cx", function(d) {
                    return xScale(new Date(d[0]));
                })
                .attr("cy", function(d) {
                    return yScale(d[1]);
                })
                .attr("fill", function(d){return d[2];})
                .attr("r", 4);
                
        }
    },[])
    
    return (
        <div id="graph-area">

            <div id="graph"></div>
            
        </div>
    )
}

といった式で

このような散布図がかけました! 上記のjsファイルはcomponentsとしてメインファイルから読み込んでいます。

数値が大きすぎてx軸の数字が重なってしまっているところは要改善ですね、、、笑

おわりに

 今回はnext.jsにグラフなどの機能を追加していきました。正直まだSSGの概念やDOM操作などなんとなく、という感じではありますが、しばらく手探りしながら使えるようになっていこうと思います。

 jsのライブラリはReactベースのものも多いので、慣れてきたら拡張性も高まりそうです。情報発信いいぞーって言われていましたが、今回で44回目になるこの連載を続けていなければ、今コーディングを続けていたかもわからないくらい、モチベーションと自分の中での発見・理解を深めるツールになってきています。もちろんネタを必死に探し回るときもよくありますが笑

 根気と戦いながら今後も制作を進めていきます! ではでは!

この記事が気に入ったらサポートをしてみませんか?